



#include "../inc/dllemvb.h"


#ifdef CONTACT_EMV




unsigned short Emvb_ProcessSaveCardRetData(unsigned char *datain,unsigned short *index,unsigned char *dataout,unsigned char *datalen,unsigned short databufsize)
{
    unsigned short len;
    unsigned short tempindex;
	unsigned short tempdatalen = 1;

	tempindex = *index;
	if(ParseExtLen(datain,&tempindex,&len))
	{
		return 0xffff;
	}
	if(datalen != NULL)
	{
		if(len > databufsize)
		{
			*datalen = databufsize;
		}
		else
		{
			*datalen = len;
		}

		tempdatalen = *datalen;
	}
	
	if(dataout != NULL)
	{
		memcpy(dataout,&datain[tempindex],tempdatalen);
	}

	tempindex += len;
	
	*index = tempindex;
	
	return len;
}



/*******************************************************************
��    ��:
��������: int Emv_MatchTermAID(unsigned char* aid,unsigned char aidLen,TERMAPP *Applist,unsigned char listnum)
��������: �ն��б�ƥ��
��ڲ���: aid - ��Ҫƥ���Ӧ������
          aidLen -  ��Ҫƥ���Ӧ�õĳ���
          Applist -   �ն�Ӧ���б�
          listnum -�ն�Ӧ���б�����
�� �� ֵ: i != -1��Ӧ���ն��б��е�Ӧ�õ�Ӧ�ú�
          -1   ƥ��ʧ��
��ص���:
��    ע:
�޸���Ϣ:  sxl0215
********************************************************************/
/*
int Emv_MatchTermAID(unsigned char* aid,unsigned char aidLen,TERMAPP *Applist,unsigned char listnum)
{
	int i,j;

	#ifdef SXL_DEBUG
    emvb_printf("\r\nEmv_MatchTermAID listnum = %d",listnum);
	#endif
	
	for(i=0;i<listnum;i++)
	{
	    #ifdef SXL_DEBUG
        emvb_printf("\r\n Emv_MatchTermAID i = %d %d %d\r\n ",i,aidLen,(Applist+i)->AIDLen);
		for(j = 0;j<aidLen;j++)
		{
			emvb_printf("%02x ",aid[j]);
		}
		emvb_printf("\r\n");
		for(j = 0;j<(Applist+i)->AIDLen;j++)
		{
			emvb_printf("%02x ",Applist[i].AID[j]);
		}
		emvb_printf("\r\n");
		#endif
		//����ʱ�Ͷ�����෴20110426
		if((Applist+i)->ASI!=PARTIAL_MATCH)	//����ƥ��
		{
			if(!memcmp(aid,(Applist+i)->AID,(Applist+i)->AIDLen))
				return i;
		}
		else//exact match
		{
			if(!memcmp(aid,(Applist+i)->AID,aidLen))	//��ȫƥ��
				return i;
		}
	}
	return -1;
}
*/

/*******************************************************************
��    ��:
��������: ����SELECT����صĿ�����
��ڲ���: selectRet - ���ļ�ѡ��Ӧ��ṹ��
          DataOut -  �����ص�����
          LenOut -   �����ص����ݳ���
�� �� ֵ: EMV_OK��0��-�ɹ�
          ERR_EMV_IccDataFormat��34�� - IC�����ݸ�ʽ��
��ص���:
��    ע:
�޸���Ϣ: 20130731
********************************************************************/
unsigned char Emvb_ReadSelectRetData(SELECT_RET* selectRet,unsigned char* DataOut,unsigned short LenOut)
{
	//unsigned char j,k;
	unsigned short index,indexFCI,indexFCIProp,len,lenFCI,lenFCIProp;
	int indexIssuerDiscret,lenIssuerDiscret;
	
	index=0;
	if(DataOut[index]!=0x6F)	//FCIģ���ʶ
	{ 
		return ERR_EMV_IccDataFormat; //FCI template
	}
	index++;
    
    if(ParseExtLen(DataOut,&index,&lenFCI))
    {
    	return ERR_EMV_IccDataFormat;
    }
	indexFCI=index;
	
	while(index<indexFCI+lenFCI)
	{
		if(index>=LenOut) return ERR_EMV_IccDataFormat;
		if(DataOut[index]==0xFF || DataOut[index]==0x00) { index++; continue;}
		else if(DataOut[index]==0x84)	//DF��
		{
			if(selectRet->DFNameExist==1) return ERR_EMV_IccDataFormat;
			index++;

			len = Emvb_ProcessSaveCardRetData(DataOut,&index,selectRet->DFName,&selectRet->DFNameLen,16);
			if(len >16)
			{
				return ERR_EMV_IccDataFormat;
			}
			
			selectRet->DFNameExist=1;


			//termpcardinfo->DFNameLen = selectRet->DFNameLen;
			//memcpy(termpcardinfo->DFName,selectRet->DFName,termpcardinfo->DFNameLen);
			
			
		}
		else if(!memcmp(DataOut+index,"\x9F\x11",2)) //ICTI
		{
		    if(selectRet->ICTIExist)
		    {
		    	return ERR_EMV_EmvDataFormat;
		    }
			index += 2;
			len = Emvb_ProcessSaveCardRetData(DataOut,&index,&selectRet->ICTI,NULL,1);
			if(len != 1)
			{
				return ERR_EMV_IccDataFormat;
			}
			selectRet->ICTIExist=1;
		}
		else if(!memcmp(DataOut+index,"\x9F\x12",2)) //App Prefer Name
		{
		    if(selectRet->PreferNameExist)
		    {
		    	return ERR_EMV_EmvDataFormat;
		    }
			index+=2;
			len = Emvb_ProcessSaveCardRetData(DataOut,&index,selectRet->PreferName,&selectRet->PreferNameLen,16);
			if(len == 0xFFFF)
			{
				return ERR_EMV_IccDataFormat;
			}
			selectRet->PreferNameExist=1;
			
		}
		else if(DataOut[index]==0xA5)	//FCI����ר��ģ��
		{
			selectRet->FCIPropExist=1;
			index++;

			if(ParseExtLen(DataOut,&index,&lenFCIProp))
			{
				return ERR_EMV_IccDataFormat;
			}
			indexFCIProp=index;

			
			while(index<indexFCIProp+lenFCIProp)
			{
				if(index>=LenOut) return ERR_EMV_IccDataFormat;
				if(DataOut[index]==0xFF || DataOut[index]==0x00) { index++; continue;}
				else if(DataOut[index]==0x88)//SFI�ļ�
				{
					if(selectRet->SFIExist==1) return ERR_EMV_IccDataFormat;
					index++;
					len = Emvb_ProcessSaveCardRetData(DataOut,&index,&selectRet->SFI,NULL,1);
					if(len != 1)
					{
						return ERR_EMV_IccDataFormat;
					}
					selectRet->SFIExist=1;
				}
				else if(!memcmp(DataOut+index,"\x5F\x2D",2)) //Language preference
				{
					index+=2;

					len = Emvb_ProcessSaveCardRetData(DataOut,&index,selectRet->LangPrefer,&selectRet->LangPreferLen,8);
					if(len == 0xffff)
					{
						return ERR_EMV_IccDataFormat;
					}
					selectRet->LangPreferExist=1;
				}
				else if(!memcmp(DataOut+index,"\x9F\x11",2)) //ICTI
				{
				    index += 2;
				    if(selectRet->ICTIExist)
				    {
				    	return ERR_EMV_EmvDataFormat;
				    }
					
					len = Emvb_ProcessSaveCardRetData(DataOut,&index,&selectRet->ICTI,NULL,1);
					if(len != 1)
					{
						return ERR_EMV_IccDataFormat;
					}
					
					selectRet->ICTIExist=1;
				}
				else if(DataOut[index]==0x50) //App Label
				{
				    index++;

					len = Emvb_ProcessSaveCardRetData(DataOut,&index,selectRet->AppLabel,&selectRet->AppLabelLen,16);
					if(len == 0xffff)
					{
						return ERR_EMV_IccDataFormat;
					}
					selectRet->AppLabelExist=1;
				}
				else if(DataOut[index]==0x87)//App Priority Indicator
				{
				    index++;
					if(selectRet->PriorityExist==1) return ERR_EMV_IccDataFormat;

					len = Emvb_ProcessSaveCardRetData(DataOut,&index,&selectRet->Priority,NULL,1);
					if(len != 1)
					{
						return ERR_EMV_IccDataFormat;
					}
					
					selectRet->PriorityExist=1;
				}
				else if(!memcmp(DataOut+index,"\x9F\x38",2)) //PDOL
				{
					if(selectRet->PDOLExist==1) return ERR_EMV_IccDataFormat;
					index+=2;
					
					len = Emvb_ProcessSaveCardRetData(DataOut,&index,NULL,&selectRet->PDOLLen,255);
					if(len == 0xffff)
					{
						return ERR_EMV_IccDataFormat;
					}
					
					selectRet->PDOLExist=1;
				}
				else if(!memcmp(DataOut+index,"\x9F\x12",2)) //App Prefer Name
				{
				    if(selectRet->PreferNameExist)
				    {
				    	return ERR_EMV_EmvDataFormat;
				    }
					index+=2;

					len = Emvb_ProcessSaveCardRetData(DataOut,&index,selectRet->PreferName,&selectRet->PreferNameLen,16);
					if(len == 0xffff)
					{
						return ERR_EMV_IccDataFormat;
					}
					
					selectRet->PreferNameExist=1;
					
				}
				else if(!memcmp(DataOut+index,"\xBF\x0C",2)) //FCI Issuer Discretionary Data
				{
					if(selectRet->IssuerDiscretExist==1) return ERR_EMV_IccDataFormat;
					index+=2;
					if(ParseExtLen(DataOut,&index,&len))
					{
						return ERR_EMV_IccDataFormat;
					}
					selectRet->IssuerDiscretLen=len;   //sxl 090211
					//memcpy(selectRet->IssuerDiscret,DataOut+index,len);
					selectRet->IssuerDiscretExist=1;

					indexIssuerDiscret=index;
					lenIssuerDiscret=len;
					while(index<indexIssuerDiscret+lenIssuerDiscret)
					{
						if(index>=LenOut) return ERR_EMV_IccDataFormat;
						if(DataOut[index]==0xFF || DataOut[index]==0x00) { index++; continue;}
						else if(!memcmp(DataOut+index,"\x9F\x4D",2))//Log Entry
						{
							if(selectRet->LogEntryExist==1) return ERR_EMV_IccDataFormat;
							index+=2;

							len = Emvb_ProcessSaveCardRetData(DataOut,&index,NULL,&selectRet->LogEntryLen,255);
							if(len == 0xffff)
							{
								return ERR_EMV_IccDataFormat;
							}
							
							selectRet->LogEntryExist=1;
						}
						else
						{
							if(Emvb_DataDiscard(DataOut,&index) != EMV_OK)
						    {
						    	return ERR_EMV_IccDataFormat;
						    }
						}

					}
					
				}
				else//other unknown TLV data
				{
					if(Emvb_DataDiscard(DataOut,&index) != EMV_OK)
				    {
				    	return ERR_EMV_IccDataFormat;
				    }
				}
			}
			if(index!=indexFCIProp+lenFCIProp)
				return ERR_EMV_IccDataFormat;
		}
		else if(!memcmp(DataOut+index,"\x9F\x38",2)) //add lechan 20070323 for case v2cl0320006
		{
			return ERR_EMV_IccDataFormat;
		}
		else
		{
		    if(Emvb_DataDiscard(DataOut,&index) != EMV_OK)
		    {
		    	return ERR_EMV_IccDataFormat;
		    }
		}
        
	}
	if(index!=indexFCI+lenFCI)
		return ERR_EMV_IccDataFormat;
	
	return EMV_OK;

}


/*******************************************************************
��    ��:
��������: ����SELECT����صĿ�����
��ڲ���: indexDF - DF����
          SELECT_RET -  ѡ���ļ��ṹ��
          apdu_r -   �����ص�����
�� �� ֵ: EMV_OK��0��-�ɹ�
          ERR_EMV_IccDataFormat��34�� - IC�����ݸ�ʽ��
          ERR_EMV_IccReturn -�������󷵻�
          ERR_BLOCKORFORMATERR -����
��ص���:
��    ע:
�޸���Ϣ:   20130731
********************************************************************/
unsigned char Emvb_SelectDFRetData(SELECT_RET *selectRet,APDU_RESP *apdu_r,EMVBAppUnionStruct *tempAppUnionStruct)
{
	unsigned char sfi;
	
	if(apdu_r->SWA==0x90 && apdu_r->SWB==0x00)
	{
		memset(selectRet,0,sizeof(SELECT_RET));
		if(Emvb_ReadSelectRetData(selectRet,apdu_r->DataOut,apdu_r->LenOut)!=EMV_OK) 
		{
			return ERR_EMV_IccDataFormat;
		}
		if(selectRet->DFNameExist==0 || selectRet->FCIPropExist==0 || selectRet->SFIExist==0)
		{
			return ERR_EMV_IccDataFormat;
		}
		
		
		sfi=selectRet->SFI;
		if(sfi<1 || sfi>10 )		//EMV SFI��1��10����Ч
		{
			return ERR_EMV_IccDataFormat;//sfi must be 1-10
		}
        
		
		return EMV_OK;
        
		
	}
	else if(apdu_r->SWA==0x6A && apdu_r->SWB==0x81)  //card block or command not supported,terminate session.
	{
		return ERR_BLOCKORFORMATERR;                //sxl ������Ҫע��
	}
	else 
	{
		return ERR_EMV_IccReturn;
	}
}






/*******************************************************************
��    ��:
��������: void PostReadReocrd(APDU_SEND *apdu_s,unsigned char sfi,unsigned char record_num)
��������: ����RECORD����صĿ�����
��ڲ���: APDU_SEND - ����ͽṹ
          sfi
          record_num - ��¼��
�� �� ֵ: ��
��ص���:
��    ע:
�޸���Ϣ:     20130731
********************************************************************/		
void PostReadReocrd(APDU_SEND *apdu_s,unsigned char sfi,unsigned char record_num)
{
    
	memcpy(apdu_s->Command,"\x00\xB2",2);
	apdu_s->Command[2]=record_num;  //record number
	apdu_s->Command[3]= sfi|0x04;
	apdu_s->Lc=0;
	apdu_s->Le=256;//Le=0(256)
	apdu_s->EnableCancel = 1;       //ʹ�ܰ�ȡ����
    
    
}


/*******************************************************************
��    ��:
��������: unsigned char Emv_ReadRecordRetData(unsigned char indexDF,APDU_RESP *apdu_r,unsigned short LenOut,AppUnionStruct *App_UnionStruct)
��������: ����RECORD����صĿ�����
��ڲ���: indexDF- DF LIST������
          apdu_r - ��Ӧ��ṹ��
          LenOut -   �����ص����ݳ���
          App_UnionStruct -���Ͻṹ��ָ��
�� �� ֵ: EMV_OK��0��-�ɹ�
          ERR_EMV_IccDataFormat��34�� - IC�����ݸ�ʽ��
          ERR_EMV_IccReturn  -�������󷵻�
��ص���:
��    ע:
�޸���Ϣ:  20130731
********************************************************************/
unsigned char Emvb_ReadRecordRetData(APDU_RESP *apdu_r,EMVBAppUnionStruct *App_UnionStruct)
{
    //unsigned char k;
	int matchNum;
	unsigned short index,len;
	unsigned short indexRecord,indexEntry,lenRecord,lenEntry;	
	unsigned char *tempappnum;
	
	RECORD_PSE recordPSE;
	
	LISTAPPDATA *tempAppAppData;

    TERMAPP tempAppTermApp;

	tempAppAppData = App_UnionStruct->EMVTradeParam->AppListCandidate;
	tempappnum = &(App_UnionStruct->EMVTradeParam->AppListCandidatenum);
    
	
	if(apdu_r->SWA==0x90 && apdu_r->SWB==0x00) //PSE Dir Record found ok.
	{
		index=0;
		if(apdu_r->DataOut[index]!=0x70) return ERR_EMV_IccDataFormat;
		index++;


		if(ParseExtLen(apdu_r->DataOut,&index,&lenRecord))
		{
			return ERR_EMV_IccDataFormat;
		}
		indexRecord=index;

		while(index<indexRecord+lenRecord)
		{
			if(index>=apdu_r->LenOut) return ERR_EMV_IccDataFormat;

			if(apdu_r->DataOut[index]==0xFF || apdu_r->DataOut[index]==0x00)
			{ 
				index++; 
				continue;
			}
			else if(apdu_r->DataOut[index]==0x61)
			{
				index++;
				if(ParseExtLen(apdu_r->DataOut,&index,&lenEntry))
				{
					return ERR_EMV_IccDataFormat;
				}
				indexEntry=index;
				memset((unsigned char*)&recordPSE,0,sizeof(RECORD_PSE));
				while(index<indexEntry+lenEntry)
				{
					if(index>=apdu_r->LenOut) return ERR_EMV_IccDataFormat;

					if(apdu_r->DataOut[index]==0xFF || apdu_r->DataOut[index]==0x00) 
					{ 
						index++; 
						continue;
					}
					else if(apdu_r->DataOut[index]==0x9D)//DDF
					{
						if(recordPSE.DFNameExist==1) return ERR_EMV_IccDataFormat;
						index++;

						len = Emvb_ProcessSaveCardRetData(apdu_r->DataOut,&index,recordPSE.DFName,&recordPSE.DFNameLen,16);
						if(len == 0xffff)
						{
							return ERR_EMV_IccDataFormat;
						}
						
						recordPSE.DFNameExist=1;
						recordPSE.Type=1;
						
					}
					else if(apdu_r->DataOut[index]==0x4F)//ADF
					{
						if(recordPSE.DFNameExist==1) return ERR_EMV_IccDataFormat;
						index++;

						len = Emvb_ProcessSaveCardRetData(apdu_r->DataOut,&index,recordPSE.DFName,&recordPSE.DFNameLen,16);
						if(len == 0xffff)
						{
							return ERR_EMV_IccDataFormat;
						}
						
						recordPSE.DFNameExist=1;
						recordPSE.Type=2;
					}
					else if(apdu_r->DataOut[index]==0x50)
					{
						if(recordPSE.AppLabelExist==1) return ERR_EMV_IccDataFormat;
						index++;

						len = Emvb_ProcessSaveCardRetData(apdu_r->DataOut,&index,recordPSE.AppLabel,&recordPSE.AppLabelLen,16);
						if(len == 0xffff)
						{
							return ERR_EMV_IccDataFormat;
						}
						
						recordPSE.AppLabelExist=1;
                        
						
					}
					else if(!memcmp(apdu_r->DataOut+index,"\x9F\x12",2)) //App Prefer Name
					{
						if(recordPSE.PreferNameExist==1) return ERR_EMV_IccDataFormat;
						index+=2;

						len = Emvb_ProcessSaveCardRetData(apdu_r->DataOut,&index,recordPSE.PreferName,&recordPSE.PreferNameLen,16);
						if(len == 0xffff)
						{
							return ERR_EMV_IccDataFormat;
						}
						
						recordPSE.PreferNameExist=1;
					}
					else if(apdu_r->DataOut[index]==0x87)
					{
						if(recordPSE.PriorityExist==1) return ERR_EMV_IccDataFormat;
						index += 1;

						len = Emvb_ProcessSaveCardRetData(apdu_r->DataOut,&index,&recordPSE.Priority,NULL,1);
						if(len == 0xffff)
						{
							return ERR_EMV_IccDataFormat;
						}
						
						recordPSE.PriorityExist=1;
					}
					else if(apdu_r->DataOut[index]==0x73)
					{
						if(recordPSE.DirDiscretExist==1) return ERR_EMV_IccDataFormat;
						index++;

						len = Emvb_ProcessSaveCardRetData(apdu_r->DataOut,&index,NULL,&recordPSE.DirDiscretLen,255);
						if(len == 0xffff)
						{
							return ERR_EMV_IccDataFormat;
						}
						
						recordPSE.DirDiscretExist=1;
					}
					else//ingnore other data
					{
						if(Emvb_DataDiscard(apdu_r->DataOut,&index) != EMV_OK)
					    {
					    	return ERR_EMV_IccDataFormat;
					    }
					}
				}
				if(index!=indexEntry+lenEntry) 
					return ERR_EMV_IccDataFormat;
				if(recordPSE.Type==2 && recordPSE.DFNameExist==1 && recordPSE.AppLabelExist==1)// ADF
				{
					//The ADF doesn't match with terminal AID,continue process next entry without adding it to candidate list.
					matchNum= App_UnionStruct->check_MatchTermAID(0,recordPSE.DFName,recordPSE.DFNameLen,&tempAppTermApp,ICC_KERNEL_ID_0_EMV);
                    #ifdef EMVB_DEBUG
                    emvb_printf("\r\nmatchnum = %d\r\n",matchNum);
					#endif

					if(matchNum < 0 )
					{
						continue;
					}

					(tempAppAppData + (*tempappnum))->tradetypevalue = tempAppTermApp.tradetypevalue;
					(tempAppAppData + (*tempappnum))->AidInTermLen = tempAppTermApp.AIDLen;
					memcpy((tempAppAppData + (*tempappnum))->AidInTerm,tempAppTermApp.AID,(tempAppAppData + (*tempappnum))->AidInTermLen);
					
					memcpy((tempAppAppData + (*tempappnum))->AID,recordPSE.DFName,recordPSE.DFNameLen);
					(tempAppAppData + (*tempappnum))->AIDLen=recordPSE.DFNameLen;
					memcpy((tempAppAppData + (*tempappnum))->AppLabel,recordPSE.AppLabel,recordPSE.AppLabelLen);
					(tempAppAppData + (*tempappnum))->AppLabelLen=recordPSE.AppLabelLen;
				
					if(recordPSE.PreferNameExist==1)
					{
						memcpy((tempAppAppData + (*tempappnum))->PreferName,recordPSE.PreferName,recordPSE.PreferNameLen);
						(tempAppAppData + (*tempappnum))->PreferNameLen=recordPSE.PreferNameLen;
					}
					if(recordPSE.PriorityExist==1)
						(tempAppAppData + (*tempappnum))->Priority=recordPSE.Priority;
					//if(recordPSE.DirDiscretExist==1)
					//{
					//	memcpy((tempAppAppData + (*tempappnum))->DirDiscret,recordPSE.DirDiscret,recordPSE.DirDiscretLen);
					//	(tempAppAppData + (*tempappnum))->DirDiscretLen=recordPSE.DirDiscretLen;
					//}
					
			
					(*tempappnum)++;
					

				}
				else if(recordPSE.Type==1 && recordPSE.DFNameExist==1)
				{
					
				}
				else
				{
					return ERR_EMV_IccDataFormat;
				}
				
			}
			else//unknown tag data
			{
				if(Emvb_DataDiscard(apdu_r->DataOut,&index) != EMV_OK)
			    {
			    	return ERR_EMV_IccDataFormat;
			    }				
			}
		}
		if(index!=indexRecord+lenRecord)
			return ERR_EMV_IccDataFormat;
	} //if PSE directory record found.(Read Record)
	else if(apdu_r->SWA==0x6A && apdu_r->SWB==0x83) //no DF Record for this record number.
	{
		return EMV_OK;
	}
	else 
	{
		return ERR_EMV_IccReturn;
	}
	
	return EMV_PARSESUC;
}


//20130731
unsigned char Emvb_SelectDDF(EMVBAppUnionStruct *tempAppUnionStruct)
{
	unsigned char retCode;
    APDU_SEND apdu_s;
	APDU_RESP apdu_r;
	SELECT_RET selectRet;
	unsigned char Recordnum;

	LISTAPPDATA *tempAppAppData;
	unsigned char i;

	
    #ifdef EMVB_DEBUG
    emvb_printf("\r\nEmvb_SelectDDF10\r\n");
	#endif
    EMVB_COMMAND_SELECT((unsigned char *)"1PAY.SYS.DDF01",14,0,&apdu_s);

	#ifdef EMVB_DEBUG
    emvb_printf("\r\nEmvb_SelectDDF11: %08x %08x\r\n",tempAppUnionStruct,tempAppUnionStruct->EMVB_qPBOCIccIsoCommand);
	#endif
    tempAppUnionStruct->EMVB_qPBOCIccIsoCommand(&apdu_s,&apdu_r);
    if(apdu_r.ReadCardDataOk != EMV_OK)
    {
    	return ERR_APP_TIMEOUT;
    }

	#ifdef EMVB_DEBUG
    emvb_printf("\r\nEmvb_SelectDDF1\r\n");
	#endif
	retCode = Emvb_SelectDFRetData(&selectRet,&apdu_r,tempAppUnionStruct);
	#ifdef EMVB_DEBUG
    emvb_printf("\r\nEmvb_SelectDFRetData = %d\r\n",retCode);
	#endif
    if(retCode != EMV_OK)
    {
    	return retCode;
    }
    
	Recordnum = 1;
    
	
    while(1)
    {
        PostReadReocrd(&apdu_s,selectRet.SFI<<3,Recordnum);
        tempAppUnionStruct->EMVB_qPBOCIccIsoCommand(&apdu_s,&apdu_r);
	    if(apdu_r.ReadCardDataOk != EMV_OK)
	    {
	    	return ERR_APP_TIMEOUT;
	    }
        
		
		retCode = Emvb_ReadRecordRetData(&apdu_r,tempAppUnionStruct);
		#ifdef EMVB_DEBUG
        emvb_printf("\r\nEmvb_ReadRecordRetData retCode = %d\r\n",retCode);
		#endif
		if(retCode != EMV_PARSESUC)
		{
			break;
		}

		Recordnum++;
    }

	
	tempAppAppData = tempAppUnionStruct->EMVTradeParam->AppListCandidate;
	//save DF name
    if(retCode == EMV_OK&&tempAppUnionStruct->EMVTradeParam->AppListCandidatenum)
    {
        
    	dllemvb_avl_createsettagvalue((unsigned char *)TAG_DFName,selectRet.DFName,selectRet.DFNameLen);
		if(selectRet.ICTIExist)
		{
			//dllemvb_avl_set((unsigned char *)TAG_ICTI,selectRet.ICTI);

            for(i = 0;i < tempAppUnionStruct->EMVTradeParam->AppListCandidatenum;i++)
            {
				(tempAppAppData + i)->ICTILen = 1;
				(tempAppAppData + i)->ICTI = selectRet.ICTI;
            }
			
		}
		
    }
    
	#ifdef EMVB_DEBUG
    emvb_printf("\r\nEmvb_SelectDDF retCode = %d\r\n",retCode);
	#endif
	return retCode;
    
}

/*******************************************************************
��    ��:
��������: �������ն��б��ж��ļ�
��ڲ���: indexDF - DF����
          SELECT_RET -  ѡ���ļ��ṹ��
          apdu_r -   �����ص�����
�� �� ֵ: EMV_OK��0��-�ɹ�
          ERR_EMV_IccDataFormat��34�� - IC�����ݸ�ʽ��
          ERR_EMV_IccReturn -�������󷵻�
          ERR_BLOCKORFORMATERR -����
��ص���:
��    ע:
�޸���Ϣ:    20130731
********************************************************************/
unsigned char Emvb_SelectTermRetData(APDU_RESP *apdu_r,EMVBAppUnionStruct *tempAppUnionStruct,unsigned char appnumindex,TERMAPP *temptermapp)
{
    SELECT_RET selectRet;
    unsigned char retCode;
	
    LISTAPPDATA *tempAppData;
	unsigned char *tempapplistnum;

	#ifdef EMVB_DEBUG
	unsigned char i;
	#endif
	
	
	tempAppData = tempAppUnionStruct->EMVTradeParam->AppListCandidate;
	tempapplistnum = &(tempAppUnionStruct->EMVTradeParam->AppListCandidatenum);
    
	
	if(apdu_r->SWA==0x6A && apdu_r->SWB==0x81 )//card block or command not support
	{
		return ERR_EMV_CardBlock;
	} 
	else if(apdu_r->SWA==0x62 && apdu_r->SWB==0x83)//App is blocked
	{
		//return EMV_APPBLOCK;  //sxl20161211
		memset((unsigned char*)&selectRet,0,sizeof(SELECT_RET));
		retCode=Emvb_ReadSelectRetData(&selectRet,apdu_r->DataOut,apdu_r->LenOut);	
		if(retCode!=EMV_OK)
		{
			return ERR_EMV_IccDataFormat;
		}

		if(selectRet.DFNameExist==0 || selectRet.FCIPropExist==0)
		{	
			return ERR_EMV_IccDataFormat;
		}
		
		if(!memcmp((temptermapp+appnumindex)->AID,selectRet.DFName,(temptermapp+appnumindex)->AIDLen))
		{
			if((temptermapp+appnumindex)->AIDLen==selectRet.DFNameLen)
			{
				retCode = APPSELECT_APPBLOCK_EXTRACTMATCH;
			}
			else
			{
			    retCode = APPSELECT_APPBLOCK_PARTICALMATCH;
				if((temptermapp+appnumindex)->ASI!=PARTIAL_MATCH)
				{
					retCode = EMV_NOTMATCH;
					
				}
			}

			return retCode;
		}
        else
		{
			return ERR_EMV_IccDataFormat;
		}
	}
	else if(apdu_r->SWA==0x90 && apdu_r->SWB==0x00) //Select successful
	{
		memset((unsigned char*)&selectRet,0,sizeof(SELECT_RET));
		retCode=Emvb_ReadSelectRetData(&selectRet,apdu_r->DataOut,apdu_r->LenOut);	
		if(retCode!=EMV_OK)
		{
			return ERR_EMV_IccDataFormat;
		}

		if(selectRet.DFNameExist==0 || selectRet.FCIPropExist==0)
		{	
			return ERR_EMV_IccDataFormat;
		}
		if(!memcmp((temptermapp+appnumindex)->AID,selectRet.DFName,(temptermapp+appnumindex)->AIDLen))
		{
			if((temptermapp+appnumindex)->AIDLen==selectRet.DFNameLen)
			{
				retCode = EMV_EXTRACTMATCH;
				(tempAppData+*tempapplistnum)->AidInTermLen = (temptermapp+appnumindex)->AIDLen;
				memcpy((tempAppData+*tempapplistnum)->AidInTerm,(temptermapp+appnumindex)->AID,(tempAppData+*tempapplistnum)->AidInTermLen);
				(tempAppData+*tempapplistnum)->tradetypevalue = (temptermapp+appnumindex)->tradetypevalue;
			}
			else
			{
			    retCode = EMV_PARTICALMATCH;
				if((temptermapp+appnumindex)->ASI!=PARTIAL_MATCH)
				{
					retCode = EMV_NOTMATCH;
					return retCode;	
				}

				
				(tempAppData+*tempapplistnum)->AidInTermLen = (temptermapp+appnumindex)->AIDLen;
				memcpy((tempAppData+*tempapplistnum)->AidInTerm,(temptermapp+appnumindex)->AID,(tempAppData+*tempapplistnum)->AidInTermLen);
				(tempAppData+*tempapplistnum)->tradetypevalue = (temptermapp+appnumindex)->tradetypevalue;
				#ifdef EMVB_DEBUG
				emvb_printf("\r\nselect from term:%d %d %d\r\n",appnumindex,*tempapplistnum,(tempAppData+*tempapplistnum)->AidInTermLen);
                for(i = 0;i < (tempAppData+*tempapplistnum)->AidInTermLen;i++)
                {
                	emvb_printf("%02x ",(tempAppData+*tempapplistnum)->AidInTerm[i]);
                }
				emvb_printf("\r\n");
				#endif

			}
		}
		else
		{
			return ERR_EMV_IccDataFormat;
		}

		memcpy((tempAppData+*tempapplistnum)->AID,selectRet.DFName,selectRet.DFNameLen);
		(tempAppData+*tempapplistnum)->AIDLen=selectRet.DFNameLen;        	


		memcpy((tempAppData+*tempapplistnum)->AppLabel,selectRet.AppLabel,selectRet.AppLabelLen);
		(tempAppData+*tempapplistnum)->AppLabelLen=selectRet.AppLabelLen;

		if(selectRet.PriorityExist==1)
		(tempAppData+*tempapplistnum)->Priority=selectRet.Priority;
        
        /*
		if(selectRet.PDOLExist==1)
		{
			memcpy((tempAppData+*tempapplistnum)->PDOL,selectRet.PDOL,selectRet.PDOLLen);
			(tempAppData+*tempapplistnum)->PDOLLen=selectRet.PDOLLen;
		}
		*/

		if(selectRet.LangPreferExist==1)
		{
			memcpy((tempAppData+*tempapplistnum)->LangPrefer,selectRet.LangPrefer,selectRet.LangPreferLen);
			(tempAppData+*tempapplistnum)->LangPreferLen=selectRet.LangPreferLen;
		}
        //ICTI��Ҫע��
		if(selectRet.ICTIExist==1)
		{
			(tempAppData+*tempapplistnum)->ICTI=selectRet.ICTI;
			(tempAppData+*tempapplistnum)->ICTILen = 1;    
		}
		if(selectRet.PreferNameExist==1)
		{
			memcpy((tempAppData+*tempapplistnum)->PreferName,selectRet.PreferName,selectRet.PreferNameLen);
			(tempAppData+*tempapplistnum)->PreferNameLen=selectRet.PreferNameLen;
		}
        
		/*
		if(selectRet.IssuerDiscretExist==1)
		{
			memcpy((tempAppData+*tempapplistnum)->IssuerDiscret,selectRet.IssuerDiscret,selectRet.IssuerDiscretLen);
			(tempAppData+*tempapplistnum)->IssuerDiscretLen=selectRet.IssuerDiscretLen;
		}
		*/
		
		return retCode;
	}
	else 
	{
		return EMV_PARSESUC;
	}
}


/*******************************************************************
��    ��:
��������: u8 PostReadApp(u16 i,u8 nextflag)
��������: ��Ӧ��
��ڲ���:
			1..Ӧ������.
			2�Ƿ��һ��Ӧ��
�� �� ֵ: ��
��ص���:
��    ע:
�޸���Ϣ:  20130731
********************************************************************/
void PostReadApp(unsigned short i,unsigned char nextflag,TERMAPP *temptermapp,APDU_SEND *apdu_s)
{
	if(nextflag)
		memcpy(apdu_s->Command,"\x00\xA4\x04\x02",4); //ADF,select next app with same AID 
	else 
		memcpy(apdu_s->Command,"\x00\xA4\x04\x00",4); //ADF
	apdu_s->Lc=(temptermapp+i)->AIDLen;
	
	memcpy(apdu_s->DataIn,(temptermapp+i)->AID,(temptermapp+i)->AIDLen);
	apdu_s->Le=256; 
	apdu_s->EnableCancel = 1;
	
}



/*******************************************************************
��    ��:
��������: unsigned char Emv_SelectFromTerm(AppUnionStruct *tempAppUnionStruct)
��������: �ն��б�ѡ��Ӧ��
��ڲ���: ��
�� �� ֵ: ��
��ص���:
��    ע:
�޸���Ϣ:      20130731
********************************************************************/
unsigned char Emvb_SelectFromTerm(EMVBAppUnionStruct *tempAppUnionStruct)
{
    unsigned char retCode;
    unsigned char AppNumIndex = 0;
    TERMAPP *temptermapp;//[40];
	unsigned char temptermlistnum;
	APDU_SEND apdu_s;
	APDU_RESP apdu_r;
	//LISTAPPDATA *tempAppData;
	unsigned char bSecond = 0;
    unsigned char *tempapplistnum;
    #ifdef EMVB_DEBUG
    LISTAPPDATA *tempAppData;
    int i;
    #endif
    
    temptermapp = (TERMAPP *)emvblib_malloc(sizeof(TERMAPP)*200);
	
    //tempAppData = tempAppUnionStruct->EMVTradeParam->AppListCandidate;
	tempapplistnum = &(tempAppUnionStruct->EMVTradeParam->AppListCandidatenum);
    
	temptermlistnum = 200;
	tempAppUnionStruct->ReadTermAID(&temptermapp[0],&temptermlistnum);
    
	#ifdef EMVB_DEBUG
    emvb_printf("\r\nEmvb_SelectFromTerm = %d %d\r\n",AppNumIndex,temptermlistnum);
	#endif
	while(AppNumIndex < temptermlistnum)
	{
	    
        #ifdef EMVB_DEBUG
	    emvb_printf("SelectFromTerm %d aidlen: %d %02x\r\n",AppNumIndex, (temptermapp + AppNumIndex)->AIDLen, (temptermapp + AppNumIndex)->tradetypevalue);
        for(i = 0;i < (temptermapp + AppNumIndex)->AIDLen; i++)
        {
            emvb_printf("%02x ", (temptermapp + AppNumIndex)->AID[i]);
        }
        emvb_printf("\r\n");
        #endif
		PostReadApp(AppNumIndex,bSecond,temptermapp,&apdu_s);
		
		tempAppUnionStruct->EMVB_qPBOCIccIsoCommand(&apdu_s,&apdu_r);
		if(apdu_r.ReadCardDataOk != EMV_OK)
		{
		    emvblib_free(temptermapp);
			return ERR_APP_TIMEOUT;
		}
		
		retCode = Emvb_SelectTermRetData(&apdu_r,tempAppUnionStruct,AppNumIndex,&temptermapp[0]);
        #ifdef EMVB_DEBUG
        emvb_printf("\r\nEmvb_SelectTermRetData retCode = %d\r\n",retCode);
		#endif
        
		if(retCode ==EMV_EXTRACTMATCH)    //��ȡ���APP����һ��RECORD
		{
			(*tempapplistnum)++;
		}
		else if(retCode ==EMV_PARTICALMATCH)    //����ƥ��
		{
			bSecond=1;
			(*tempapplistnum)++;
			continue;
			//break;
		}
		else if(retCode == APPSELECT_APPBLOCK_EXTRACTMATCH)
		{
			//����6283��������,ѡ����һ��term AID
		}
		else if(retCode == APPSELECT_APPBLOCK_PARTICALMATCH)
		{
			//����6283��������,ѡ����һ��term AID
			bSecond=1;
			continue;
		}
		else if(retCode ==EMV_NOTMATCH)       //��ƥ��
		{
			//bSecond=1;    //��ƥ���ѡ����һ��AID  //sxl20161211
			//continue;
		}
		else if(retCode == ERR_EMV_CardBlock)
		{
		    if(bSecond == 0)
		    {
		        emvblib_free(temptermapp);
				return ERR_EMV_CardBlock;
		    }
		}
		else if(retCode == EMV_APPBLOCK)     //��������Ӧ��
		{
			tempAppUnionStruct->EMVTradeParam->appblockflag=1;
			if(bSecond == 1)
			{
				//bSecond=1;
				continue;
			}

		}  
        
		
		AppNumIndex++;
		bSecond=0;
        
		
	}
	emvblib_free(temptermapp);

    #ifdef EMVB_DEBUG
    emvb_printf("Emvb_SelectFromTerm aidlist = %d \r\n", *tempapplistnum);
    tempAppData = tempAppUnionStruct->EMVTradeParam->AppListCandidate;
    for(AppNumIndex = 0; AppNumIndex < *tempapplistnum; AppNumIndex++)
    {
        for(i = 0;i < (tempAppData + AppNumIndex)->AIDLen; i++)
        {
            emvb_printf("%02x ", (tempAppData + AppNumIndex)->AID[i]);
        }
        emvb_printf("\r\n");
    }
    emvb_printf("\r\n");
    #endif

    return EMV_OK;
	
}




//20130731
unsigned char Emvb_GetAppCandidate(EMVBAppUnionStruct *tempApp_UnionStruct)
{

    unsigned char retcode = EMV_OK;
    
	#ifdef EMVB_DEBUG
    emvb_printf("\r\nEmvb_GetAppCandidate11\r\n");
	#endif
	retcode = Emvb_SelectDDF(tempApp_UnionStruct);
	#ifdef EMVB_DEBUG
    emvb_printf("\r\nEmvb_SelectDDF retcode = %d\r\n",retcode);
	#endif
	if(retcode != EMV_OK)
	{
	    if(retcode == ERR_BLOCKORFORMATERR)
	    {
	    	retcode = ERR_EMV_CardBlock;
	    }
	}
    if(retcode==EMV_OK)           //�鿴�Ƿ��ҵ�Ӧ��
    {
		if(tempApp_UnionStruct->EMVTradeParam->AppListCandidatenum == 0)
		{
			retcode = APPSEL_PSENOTFOUND;
		}
    }
    
	
	if(retcode == EMV_OK || retcode == ERR_EMV_CardBlock || retcode == ERR_APP_TIMEOUT)    //�ն��б�ѡ��
	{
		return retcode;
	}
	tempApp_UnionStruct->EMVTradeParam->AppListCandidatenum = 0;
	memset((unsigned char *)tempApp_UnionStruct->EMVTradeParam->AppListCandidate, 0, sizeof(LISTAPPDATA) * 16);
    retcode = Emvb_SelectFromTerm(tempApp_UnionStruct);

	return retcode;
	
}



//Ӧ��ѡ��
//20130731
unsigned char EMVb_AppSelect(EMVBAppUnionStruct *tempApp_UnionStruct)
{
	unsigned char retcode;
    
	#ifdef EMVB_DEBUG
    emvb_printf("\r\nEMVb_AppSelect: %08x %08x\r\n",tempApp_UnionStruct,tempApp_UnionStruct->EMVB_qPBOCIccIsoCommand);
	#endif
	
	retcode = Emvb_GetAppCandidate(tempApp_UnionStruct);      //���ն�Ӧ���б�����
	
	return retcode;
	
}



/*******************************************************************
��    ��:
��������: unsigned char Emv_ChooseAppList(AppUnionStruct *tempApp_UnionStruct,unsigned char *AppPriority,unsigned char *AppSeq,unsigned char *seqtype)
��������: Ӧ���б�ѡ��
��ڲ���:
		  App_UnionStruct -���Ͻṹ
		  AppPriority - Ӧ�����ȼ�
		  AppSeq - Ӧ������
		  seqtype - Ӧ����������
�� �� ֵ:
��ص���:
��    ע:
�޸���Ϣ:     20130731
********************************************************************/
unsigned char Emvb_ChooseAppList(EMVBAppUnionStruct *tempApp_UnionStruct)
{
	unsigned char i,j,bPriority,temp; //bConfirm,
	LISTAPPDATA *tempAppAppData;
    unsigned char noprioritynum;
	unsigned char tmpapprtiority[16];
	unsigned char tmpseq[16];
	
    tempAppAppData = tempApp_UnionStruct->EMVTradeParam->AppListCandidate;
    
    
	tempApp_UnionStruct->EMVTradeParam->SelectedAppNo = 0xff;
		
	
	if(tempApp_UnionStruct->EMVTradeParam->SelectedAppNo>tempApp_UnionStruct->EMVTradeParam->AppListCandidatenum)
	{
		bPriority=1;
		//bConfirm=1;
		for(i=0;i<tempApp_UnionStruct->EMVTradeParam->AppListCandidatenum;i++)
		{
			tempApp_UnionStruct->EMVTradeParam->DispSeqListData.AppPriority[i]=(tempAppAppData+i)->Priority & 0x0F;
			tempApp_UnionStruct->EMVTradeParam->DispSeqListData.AppSeq[i]=i;
		}
		if(tempApp_UnionStruct->EMVTradeParam->AppListCandidatenum==1)
		{		
			if((tempAppAppData->Priority & 0x80) || tempApp_UnionStruct->EMVTradeParam->bretforminit)
			{	
				if(bProvideConfirm)
				{
				    tempApp_UnionStruct->EMVTradeParam->DispSeqListData.seqtype = 0;
					return EMV_USERSELECT;
				}
			}
			else
			{
				tempApp_UnionStruct->EMVTradeParam->SelectedAppNo = 0;
			}

		}
		else
		{
			for(j=0;j<tempApp_UnionStruct->EMVTradeParam->AppListCandidatenum-1;j++)
			{
				for(i=0;i<tempApp_UnionStruct->EMVTradeParam->AppListCandidatenum-1-j;i++)
				{
					if(tempApp_UnionStruct->EMVTradeParam->DispSeqListData.AppPriority[i]>tempApp_UnionStruct->EMVTradeParam->DispSeqListData.AppPriority[i+1])
					{
						temp=tempApp_UnionStruct->EMVTradeParam->DispSeqListData.AppPriority[i];
						tempApp_UnionStruct->EMVTradeParam->DispSeqListData.AppPriority[i]=tempApp_UnionStruct->EMVTradeParam->DispSeqListData.AppPriority[i+1];
						tempApp_UnionStruct->EMVTradeParam->DispSeqListData.AppPriority[i+1]=temp;
						temp=tempApp_UnionStruct->EMVTradeParam->DispSeqListData.AppSeq[i];
						tempApp_UnionStruct->EMVTradeParam->DispSeqListData.AppSeq[i]=tempApp_UnionStruct->EMVTradeParam->DispSeqListData.AppSeq[i+1];
						tempApp_UnionStruct->EMVTradeParam->DispSeqListData.AppSeq[i+1]=temp;
					}
				}
			}
            
			//�� 00��priority��Ӧ���Ƶ����
			noprioritynum = 0;
			for(i=0;i<tempApp_UnionStruct->EMVTradeParam->AppListCandidatenum;i++)
			{
				if(tempApp_UnionStruct->EMVTradeParam->DispSeqListData.AppPriority[i]==0) //bPriority=0;
				{
					noprioritynum++;
				}
				//if(((tempAppAppData+i)->Priority & 0x80)==0) bConfirm=0;
			}
			
			if(noprioritynum)  //have no priority app
			{
				memcpy(tmpapprtiority,&tempApp_UnionStruct->EMVTradeParam->DispSeqListData.AppPriority[noprioritynum],tempApp_UnionStruct->EMVTradeParam->AppListCandidatenum - noprioritynum);
				memcpy(&tmpapprtiority[tempApp_UnionStruct->EMVTradeParam->AppListCandidatenum  - noprioritynum],tempApp_UnionStruct->EMVTradeParam->DispSeqListData.AppPriority,noprioritynum);
				memcpy(tempApp_UnionStruct->EMVTradeParam->DispSeqListData.AppPriority,tmpapprtiority,tempApp_UnionStruct->EMVTradeParam->AppListCandidatenum );
				
				memcpy(tmpseq,&tempApp_UnionStruct->EMVTradeParam->DispSeqListData.AppSeq[noprioritynum],tempApp_UnionStruct->EMVTradeParam->AppListCandidatenum - noprioritynum);
				memcpy(&tmpseq[tempApp_UnionStruct->EMVTradeParam->AppListCandidatenum  - noprioritynum],tempApp_UnionStruct->EMVTradeParam->DispSeqListData.AppSeq,noprioritynum);
				memcpy(tempApp_UnionStruct->EMVTradeParam->DispSeqListData.AppSeq,tmpseq,tempApp_UnionStruct->EMVTradeParam->AppListCandidatenum );
				
			}


			
			if(bPriority==1)
			{
				tempApp_UnionStruct->EMVTradeParam->DispSeqListData.seqtype = 2;
				return EMV_USERSELECT;
			}

			else
			{ 
				tempApp_UnionStruct->EMVTradeParam->DispSeqListData.seqtype = 1;
				return EMV_USERSELECT;
			}
			
		}
	}
	return EMV_OK;	
	
}


//Ӧ��ѡ��
//20130731
unsigned char Emvb_ChooseApp(EMVBAppUnionStruct *App_UnionStruct)
{	
	unsigned char retCode;
    
    
	//DISPSEQLISTDATA *tempdispseqlistdata;
    
    
	//tempdispseqlistdata = &(App_UnionStruct->EMVTradeParam->DispSeqListData);

	#ifdef EMVB_DEBUG
    emvb_printf("\r\nApp_UnionStruct->EMVTradeParam->AppListCandidatenum = %d\r\n",App_UnionStruct->EMVTradeParam->AppListCandidatenum);
	#endif

	if(App_UnionStruct->EMVTradeParam->AppListCandidatenum < 1)      //û�к��ն��б�ƥ��ı�ǩ
	{
		return ERR_EMV_NoAppSel;
	}
    
	
	
	retCode = Emvb_ChooseAppList(App_UnionStruct);
	if(retCode == EMV_USERSELECT)
	{
	    return EMV_USERSELECT;
	}
    
	if(App_UnionStruct->EMVTradeParam->SelectedAppNo > App_UnionStruct->EMVTradeParam->AppListCandidatenum)//No selected,end session. //if(retCode == ERR_EMV_CancelTrans)
	{
		return ERR_EMV_CancelTrans;
	}
    else
    {
    	return EMV_OK;
    }
	

	
}


unsigned char SelectContactAid(unsigned char *tempaid,EMVBAppUnionStruct *App_UnionStruct)
{
   unsigned char i;
   LISTAPPDATA *tempAppAppData;
   unsigned char *tempappnum;
   unsigned char *tempselectappno;
   
   tempAppAppData = App_UnionStruct->EMVTradeParam->AppListCandidate;
   tempappnum = &(App_UnionStruct->EMVTradeParam->AppListCandidatenum);
   tempselectappno = &(App_UnionStruct->EMVTradeParam->SelectedAppNo);

	for(i=0;i<*tempappnum;i++)
	{
		if(!memcmp(&tempaid[1],(tempAppAppData+i)->AID,(tempAppAppData+i)->AIDLen))
		{
			if(tempaid[0] == (tempAppAppData+i)->AIDLen)
			{
				*tempselectappno = i;
				return EMV_OK;
			}
		}
	}

	*tempselectappno = 0xee;
	return EMV_OK;

}



unsigned char Emvb_ChooseContactApp(EMVBAppUnionStruct *App_UnionStruct,unsigned char *tempsmstempaid)
{	
	
	//unsigned char retCode;
	
	unsigned char *tempappnum;
    unsigned char *tempselectappno;
	
	tempappnum = &(App_UnionStruct->EMVTradeParam->AppListCandidatenum);
	tempselectappno = &(App_UnionStruct->EMVTradeParam->SelectedAppNo);
	
	
	if(*tempappnum<1)      //û�к��ն��б�ƥ��ı�ǩ
	{
		return ERR_EMV_NoAppSel;
	}
	
	
	while(1)
	{
	    SelectContactAid(tempsmstempaid,App_UnionStruct); //retCode = 
	    
		if(*tempselectappno>*tempappnum)//No selected,end session. //if(retCode == ERR_EMV_CancelTrans)
		{
			return ERR_EMV_CancelTrans;
		}
        else
        {
        	return EMV_OK;
        }
	}
	
	
	
	
}


/*******************************************************************
��    ��:
��������: unsigned char Emv_UserSelectResult(AppUnionStruct *App_UnionStruct)
��������: �û�ѡ��Ӧ��
��ڲ���: ��
�� �� ֵ: ��
��ص���:
��    ע:
�޸���Ϣ:   20130731
********************************************************************/
unsigned char Emvb_UserSelectResult(EMVBAppUnionStruct *App_UnionStruct)
{
	DISPSEQLISTDATA *tempdispseqlistdata;
	
    tempdispseqlistdata = &(App_UnionStruct->EMVTradeParam->DispSeqListData);
    
	if(tempdispseqlistdata->SelectedResult == EMV_OK)
	{
		if(tempdispseqlistdata->seqtype == 0)
		{
			if(tempdispseqlistdata->SelectedNum==0) 
			{
				App_UnionStruct->EMVTradeParam->SelectedAppNo = 0;
				return EMV_OK;
			}
		}	
		else if(tempdispseqlistdata->seqtype == 1)
		{
			if(tempdispseqlistdata->SelectedNum<=App_UnionStruct->EMVTradeParam->AppListCandidatenum) 
			{
				App_UnionStruct->EMVTradeParam->SelectedAppNo = tempdispseqlistdata->SelectedNum;
				return EMV_OK;
			}
		}
		else if(tempdispseqlistdata->seqtype == 2)
		{
			if(tempdispseqlistdata->SelectedNum<=App_UnionStruct->EMVTradeParam->AppListCandidatenum) 
			{
				App_UnionStruct->EMVTradeParam->SelectedAppNo = tempdispseqlistdata->AppSeq[tempdispseqlistdata->SelectedNum];
				return EMV_OK;
			}
		}
	}
	else
	{
		return ERR_EMV_CancelTrans;
	}
	return ERR_EMV_IccReturn;
	
}



//20130731  sxl20131024�鿴read record��ʱ���Ƿ�����ظ���
unsigned char Emvb_checkifwrongtag(EMVBAppUnionStruct *tempApp_UnionStruct,unsigned char *tag,unsigned char taglen,EMVTAGCVLITEM *retrunitem,unsigned char Redundantflag)
{
	
	//int i;
	//unsigned char tagknown = 0;
	unsigned char present = 0;
	//unsigned char empty = 1;
	unsigned char tagprivateclass = 0;
    unsigned char updateRA = 0;
	unsigned char temptag[4];
	unsigned char temptaglen;
    EMVTAGCVLITEM *item = NULL;//,*item1 = NULL;
	unsigned char ret = 2;
	int ret1;
    //unsigned char *rundatabuf;
	//unsigned int rundatabuflen;
	//tag check  ��PAYPASS �Ĵ���Ҫ�ֿ�
    
	
    //�Ȳ鿴TREE���Ƿ����
    memset(temptag,0,sizeof(temptag));
	temptaglen = (taglen>3)?3:(taglen);
	memcpy(temptag,tag,temptaglen);
    item = dllemvb_avl_gettagitempointer(temptag);
	if(item != NULL)
	{
		present = 1;
		if(item->SupAppType&TAGTYPE_EMV)
		{
			//tagknown = 1;
		}
		updateRA = item->updatecondition&TAGUPDATECONDITION_RA;
		if(item->len)
		{
			//empty = 0;
		}
		
	}
    
	if(present == 0)  //check if tag known
	{
		ret1 = EMVB_TagBaseLib_read(tag,taglen,TAGTYPE_EMV,retrunitem);
        if(ret1 == 0)
        {
        	//tagknown = 1;
			updateRA = retrunitem->updatecondition&TAGUPDATECONDITION_RA;
        }
		
	}
	else
	{
	    
		memcpy(retrunitem,item,sizeof(EMVTAGCVLITEM));
		
	}
    
    
	
	if((tag[0]&0x20)== 0x00)  //sxl20131024 �ټ��
	{
		tagprivateclass = 1;   //sxl?
	}
    
	
	#ifdef EMVB_DEBUG
    emvb_printf("\r\ntagstatus = %02x %02x %02x \r\n",tagprivateclass,updateRA,present); //tagknown  empty
	#endif
    
	
    if(updateRA)  //���Ը���
    {
    	ret = 1;
    }

	  // 9F5D not emv tag
	if((tag[0] == 0x9F&&tag[1] == 0x5D)||(tag[0] == 0x9F&&tag[1] == 0x6C)
		||(tag[0] == 0x9F&&tag[1] == 0x6D)||(tag[0] == 0x9F&&tag[1] == 0x74)||
		(tag[0] == 0x9F&&tag[1] == 0x77)||(tag[0] == 0x9F&&tag[1] == 0x79)
		||(tag[0] == 0x9F&&tag[1] == 0x7A)||(tag[0] == 0x9F&&tag[1] == 0x7B))  //sxl?
	{
		ret = 2;
	}
	//��¼�Ƿ��ظ�
	if(Redundantflag&&tagprivateclass&&ret ==1)  //���Բ������ TAG����  //sxl20131024 �ټ��
	{
	    if(dllemvb_avl_checkifRedundantData(temptag))
		{
			ret = 0;
		}
	    #if 0  //sxl? need modify
	    rundatabuflen = 0;
		
		item1 = dllemvb_avl_gettagitempointer((unsigned char *)TAG_CheckRedundantData);
	    if(item1 != NULL)
	    {
	    	if(item1->len)
	    	{
	    	    rundatabuflen = item1->len;
               
	    	}
	    }
		rundatabuf = (unsigned char *)emvblib_malloc(rundatabuflen+4+temptaglen);
		memset(rundatabuf,0,rundatabuflen+4+temptaglen);
		if(rundatabuflen)
		{
			memcpy(rundatabuf,item1->data,rundatabuflen);
			if(contactless_checkifRedundantData(temptag,rundatabuf,rundatabuflen))
			{
				ret = 0;
			}
		}
		memcpy(&rundatabuf[rundatabuflen],temptag,temptaglen);
		rundatabuflen += temptaglen;
		dllemvb_avl_createsettagvalue((unsigned char *)TAG_CheckRedundantData,rundatabuf,rundatabuflen);
		emvblib_free(rundatabuf);

		#endif
		
	}
	
	/*
	if(!(tagknown&&tagprivateclass&&(updateRA == 0)))
	{
		if(tagknown)
		{
		    if(Redundantflag == 0)  //���ж��Ƿ��ظ�
		    {
		    	if(updateRA)       //ֻҪ�ǿ���updateRA�ľ͸���
		    	{
		    		#ifdef EMVB_DEBUG
	                emvb_printf("\r\nPaypass_checkifwrongtagok7\r\n");
					#endif
					ret = 1;
		    	}
		    }
			
			else
			{
				if((present == 0||empty)&&updateRA)
				{
				    #ifdef EMVB_DEBUG
	                emvb_printf("\r\nPaypass_checkifwrongtagok3\r\n");
					#endif
					ret = 1;
				}
				else
				{
				    #ifdef EMVB_DEBUG
	                emvb_printf("\r\nPaypass_checkifwrongtag3\r\n");
					#endif
					ret = 0;
				}
			}
			
		}
		else
		{
		    //tag unknown
		    
		    
			if(present)
			{
				if(empty&&updateRA)
				{
				    #ifdef EMVB_DEBUG
                    emvb_printf("\r\nPaypass_checkifwrongtagok4\r\n");
					#endif
					ret = 1;
				}
				else
				{
				    #ifdef EMVB_DEBUG
	                emvb_printf("\r\nPaypass_checkifwrongtag3\r\n");
					#endif
					ret = 0;
				}
			}
			
		}
	}
       */
    
	
	return ret;
}



//20130731
unsigned char Emvb_ParseAndStoreCardResponse(EMVBAppUnionStruct *tempApp_UnionStruct,unsigned char *DataOut,unsigned short *DataOutIndex,unsigned char *parsebInTable,unsigned char readstep)
{
	//unsigned char k;
	unsigned short index,len,tagdatalen;
	//unsigned char addvalue,ifemvtag;  //tmpdata,tagindex,tmpval,
	unsigned char bInTable;
	unsigned char tag[4],taglen;
	unsigned char ret;
	//unsigned char needdonextstep = 1;
    EMVTAGCVLITEM tagitem;

	#ifdef EMVB_DEBUG
    //EMVTAGCVLITEM *item;
	//unsigned char i;
	#endif
	
    index = *DataOutIndex;
    bInTable = 0;
    
	
	#ifdef EMVB_DEBUG
    //emvb_printf("\r\nindex111 = %d %d\r\n",index,bInTable);
	#endif

	if(DataOut[index] == 0xFF||DataOut[index] == 0x00)
	{
		index++;
		*DataOutIndex = index;
	    *parsebInTable = bInTable;
		
		return EMV_OK;
	}

	taglen = Emvb_GetTag(DataOut,index,tag);
	
	#if 0//def EMVB_DEBUG
    emvb_printf("\r\ntag:");
	for(i = 0;i < taglen;i++)
	{
		emvb_printf("%02x ",tag[i]);
	}
	emvb_printf("\r\n");
	#endif
	
	ret = Emvb_checkifwrongtag(tempApp_UnionStruct,tag,taglen,&tagitem,readstep);
	#ifdef EMVB_DEBUG
    //emvb_printf("\r\nret123 = %d\r\n",ret);
	#endif
	if(ret == 0)
    {
        #ifdef EMVB_DEBUG
        emvb_printf("\r\n%02x %02x wrong tag1\r\n",tag[0],tag[1]);
		#endif
    	return ERR_EMV_IccDataFormat;
    }
	else if(ret == 2)
	{
	    //needdonextstep = 0;
	}
    else
    {
		index += taglen;
        if(ParseExtLen(DataOut,&index,&len))   //sxl? DOL����һ���ֽڵĳ��ȣ�������TLV��׼��ʽ
		{
		    
			#ifdef EMVB_DEBUG
			emvb_printf("\r\nEmv_PaypassReadAFLRetData122313 %d\r\n",index);
			#endif
			return ERR_EMV_IccDataFormat;
		}

        tagdatalen = len;
		if(len)
		{
			if(len > tagitem.maxlen || len < tagitem.minlen)
			{
				
			    if(readstep == 1) // �鿴paywave �� qPBOC���ǲ���ҲҪ������
			    {
			    	if(memcmp(tag,TAG_AppLabel,taglen) == 0||memcmp(tag,TAG_AppPreferName,taglen) == 0||
					   memcmp(tag,TAG_ICTI,taglen) == 0||memcmp(tag,TAG_LangPrefer,taglen) == 0)
			    	{
			    		
			    		if(len > tagitem.maxlen)
			    		{
			    			tagdatalen = tagitem.maxlen;
			    		}
						
						
			    	}
					else
					{
						return ERR_EMV_IccDataFormat;
					}
			    }
				else
				{
					return ERR_EMV_IccDataFormat;
				}
				
				
			}
		}

		#if 0//def EMVB_DEBUG
	    emvb_printf("\r\ninsert tag:");
		for(i = 0;i < taglen;i++)
		{
			emvb_printf("%02x ",tag[i]);
		}
		emvb_printf("\r\n");
        
		
		
		for(i = 0;i < len;i++)
		{
			emvb_printf("%02x ",DataOut[index + i]);
		}
		emvb_printf("\r\n");
		
		#endif


		dllemvb_avl_createsettagvalue(tag,&DataOut[index],tagdatalen);
		
        
		#ifdef EMVB_DEBUG
	    
		#endif
        
		
        
		index += len;
		bInTable = 1;
    }

	#ifdef EMVB_DEBUG
    //emvb_printf("\r\nbInTable = %d\r\n",index);
	#endif
		
	
	if(bInTable == 0)
	{
		index += taglen;
        
		if(ParseExtLen(DataOut,&index,&len))
		{
		    
			#ifdef EMVB_DEBUG
			emvb_printf("\r\nEmv_PaypassReadAFLRetData121313 %d\r\n",index);
			#endif
			return ERR_EMV_IccDataFormat;
		}
        index += len;
        
		bInTable = 1;
	}

	#ifdef EMVB_DEBUG
    //emvb_printf("\r\nindex = %d %d\r\n",index,bInTable);
	#endif
	
    *DataOutIndex = index;
    *parsebInTable = bInTable;
	
	return EMV_OK;
}

/*******************************************************************
��    ��: sxl
��������: ����SELECT����صĿ�����
��ڲ���: selectRet - ���ļ�ѡ��Ӧ��ṹ��
          DataOut -  �����ص�����
          LenOut -   �����ص����ݳ���
�� �� ֵ: EMV_OK��0��-�ɹ�
          ERR_EMV_IccDataFormat��34�� - IC�����ݸ�ʽ��
��ص���:
��    ע:
�޸���Ϣ:    20130731
********************************************************************/
unsigned char Emvb_FinalReadSelectRetData(SELECT_RET* selectRet,unsigned char* DataOut,unsigned short LenOut,EMVBAppUnionStruct *tempAppUnionStruct)
{
    
	//unsigned char k; //j,
	unsigned short index,indexFCI,indexFCIProp,lenFCI,lenFCIProp,templen;  //len,
	//unsigned short indexIssuerDiscret; //,lenIssuerDiscret
	//unsigned short indexAppApp,lenAppApp;
	unsigned char ret;
	unsigned char bIntable;
    //EMVTAGCVLITEM *emvitem;
	//unsigned char temp[300];
	

	
	index=0;
	if(DataOut[index]!=0x6F)	//FCIģ���ʶ
	{ 
		return ERR_EMV_IccDataFormat; //FCI template
	}
	index++;

    if(ParseExtLen(DataOut,&index,&lenFCI))
    {
    	return ERR_EMV_IccDataFormat;
    }
	indexFCI=index;
	
	while(index<indexFCI+lenFCI)
	{
		if(index>=LenOut) return ERR_EMV_IccDataFormat;
		if(DataOut[index]==0xFF || DataOut[index]==0x00) { index++; continue;}
		else if(DataOut[index]==0x84)	//DF��
		{
			if(selectRet->DFNameExist==1) return ERR_EMV_IccDataFormat;
			index++;

			if(ParseExtLen(DataOut,&index,&templen))
			{
				return ERR_EMV_IccDataFormat;
			}

			
			selectRet->DFNameLen = templen;
			if(selectRet->DFNameLen>16) return ERR_EMV_IccDataFormat;
			memcpy(selectRet->DFName,DataOut+index,templen);
			selectRet->DFNameExist=1;
			
			index+=templen;
			
			//termpcardinfo->DFNameLen = selectRet->DFNameLen;
			//memcpy(termpcardinfo->DFName,selectRet->DFName,termpcardinfo->DFNameLen);
			dllemvb_avl_createsettagvalue((unsigned char *)TAG_DFName,selectRet->DFName,selectRet->DFNameLen);
            
			
		}
		else if(DataOut[index]==0xA5)	//FCI����ר��ģ��
		{
			selectRet->FCIPropExist=1;
			index++;

			
            if(ParseExtLen(DataOut,&index,&lenFCIProp))
            {
            	return ERR_EMV_IccDataFormat;
            }
			indexFCIProp=index;

            while(index<indexFCIProp+lenFCIProp)
            {
                
	            ret = Emvb_ParseAndStoreCardResponse(tempAppUnionStruct,DataOut,&index,&bIntable,1);
				if(ret != EMV_OK)
				{
					return ERR_EMV_IccDataFormat;
				}
            }
			if(index!=indexFCIProp+lenFCIProp)
				return ERR_EMV_IccDataFormat;

            //����BF0C
            if(tempAppUnionStruct->EMVTradeParam->ReadLogFlag == 0)
            {
            	
                #if 0 //201219 �Ȳ�����
	            indexIssuerDiscret = 0;
				emvitem = dllemvb_avl_gettagitempointer((unsigned char *)TAG_FCIDisData);
				if(emvitem != NULL)
				{
				    #ifdef EMVB_DEBUG
	                emvb_printf("\r\nparse TAG_FCIDisData\r\n");
					#endif
				    memset(temp,0,sizeof(temp));
					memcpy(temp,emvitem->data,emvitem->len);
					while(indexIssuerDiscret < emvitem->len)
					{
						ret = Emvb_ParseAndStoreCardResponse(tempAppUnionStruct,temp,&indexIssuerDiscret,&bIntable,1);
						if(ret != EMV_OK)
						{
							return ERR_EMV_IccDataFormat;
						}
					}

					if(indexIssuerDiscret != emvitem->len)
					{
						return ERR_EMV_IccDataFormat;
					}
	                
					dllemvb_avl_delete((unsigned char *)TAG_FCIDisData);
					
				}

				#endif
            }
			
		}
		else if(DataOut[index]==0x9F&&DataOut[index+1]==0x38)
		{
			return ERR_EMV_IccDataFormat;
		}
		else
		{
			if(Emvb_DataDiscard(DataOut,&index) != EMV_OK)
		    {
		    	return ERR_EMV_IccDataFormat;
		    }
		}

	}
	if(index!=indexFCI+lenFCI)
		return ERR_EMV_IccDataFormat;
	
	return EMV_OK;

}

/*******************************************************************
��    ��: sxl
��������: unsigned char Paywave_FinalSelectRetData(AppUnionStruct *App_UnionStruct)
��������: ����Paywaveѡ��Ӧ�÷�������
��ڲ���: ��
�� �� ֵ: ��
��ص���:
��    ע:
�޸���Ϣ:         20130731
********************************************************************/
unsigned char  EMVb_FinalSelectRetData(APDU_RESP *apdu_r,EMVBAppUnionStruct *tempApp_UnionStruct)
{
    //unsigned char k, i;	
    SELECT_RET selectRet;
	LISTAPPDATA *tempselectedapp;
	
	LISTAPPDATA *tempappdata;
	unsigned char tempselectedappno;
	
	//unsigned char tempselectappno;  
	//unsigned char indexPODL,TermTranFlag;
	//unsigned char *tempappnum;
    
    
	//tempappnum = &(tempApp_UnionStruct->EMVTradeParam->AppListCandidatenum);
	tempselectedapp = tempApp_UnionStruct->EMVTradeParam->SelectedApp;
	tempappdata = tempApp_UnionStruct->EMVTradeParam->AppListCandidate;
	tempselectedappno = tempApp_UnionStruct->EMVTradeParam->SelectedAppNo;
    
	
	if(apdu_r->SWA==0x90 && apdu_r->SWB==0x00)//Select OK
	{	
	    
		memset((unsigned char*)&selectRet,0,sizeof(SELECT_RET));

		if(Emvb_FinalReadSelectRetData(&selectRet,apdu_r->DataOut,apdu_r->LenOut,tempApp_UnionStruct)!=EMV_OK) 
		{
		    #ifdef EMVB_DEBUG
            emvb_printf("\r\nEmvb_FinalReadSelectRetData111\r\n");
			#endif
		    
			
			return ERR_EMV_IccDataFormat;
		}

		#ifdef EMVB_DEBUG
        emvb_printf("\r\nEmvb_FinalReadSelectRetData222\r\n");
		#endif
		
		
		if(selectRet.DFNameExist==0 || selectRet.FCIPropExist==0)
		{
			return ERR_EMV_IccDataFormat;
		}
        
		
			
		memcpy(tempselectedapp->AID,(tempappdata+tempselectedappno)->AID,(tempappdata+tempselectedappno)->AIDLen);
		tempselectedapp->AIDLen=(tempappdata+tempselectedappno)->AIDLen;

		#ifdef EMVB_DEBUG
        emvb_printf("\r\nEmvb_FinalReadSelectRetData777\r\n");
		#endif
		
		
		
	}
	else//current app selected fail,delete it from app list and select again.
	{
	    
		if(apdu_r->SWA==0x62 && apdu_r->SWB==0x83)  //APP is blocked
		{
		    tempApp_UnionStruct->EMVTradeParam->appblockflag = 1;
			if(tempApp_UnionStruct->EMVTradeParam->ReadLogFlag)
			{
			    if(Emvb_FinalReadSelectRetData(&selectRet,apdu_r->DataOut,apdu_r->LenOut,tempApp_UnionStruct)!=EMV_OK) 
				{
				    #ifdef EMVB_DEBUG
		            emvb_printf("\r\nEmvb_FinalReadSelectRetData111\r\n");
					#endif
				    
					
					return ERR_EMV_IccDataFormat;
				}
				return EMV_OK;
			}
            
			
		}
		return ERR_EMV_AppReselect;
		
	}

	//�Ƚ�AID����ѡ�е�AID���Ƹ�TermInfo
	return qPBOC_READAIDPARAMETERS;
	
}



//Ӧ������ѡ��
//20130731
unsigned char Emvb_FinalSelect(EMVBAppUnionStruct *App_UnionStruct)
{
	
	unsigned char retCode;
	APDU_SEND apdu_s;
	APDU_RESP apdu_r;
	unsigned char tempselectappno;
	LISTAPPDATA *tempAppAppData;
    
    
	
    tempAppAppData = App_UnionStruct->EMVTradeParam->AppListCandidate;
	tempselectappno = App_UnionStruct->EMVTradeParam->SelectedAppNo;
    
    
	EMVB_COMMAND_SELECT((tempAppAppData+tempselectappno)->AID,(tempAppAppData+tempselectappno)->AIDLen,0,&apdu_s);
	App_UnionStruct->EMVB_qPBOCIccIsoCommand(&apdu_s,&apdu_r);
    if(apdu_r.ReadCardDataOk != EMV_OK)
    {
    	return ERR_APP_TIMEOUT;
    }

	retCode = EMVb_FinalSelectRetData(&apdu_r,App_UnionStruct);
	if(retCode == EMV_OK||retCode == qPBOC_READAIDPARAMETERS)
	{
		if(dllemvb_avl_checkiftagexist((unsigned char *)TAG_AppLabel) == 0)
		{
			if((tempAppAppData+tempselectappno)->AppLabelLen)  // �������͵��Ƿ�ҲҪ��������
		    {
		    	dllemvb_avl_createsettagvalue((unsigned char *)TAG_AppLabel,(tempAppAppData+tempselectappno)->AppLabel,(tempAppAppData+tempselectappno)->AppLabelLen);
		    }
		}
		
		if(dllemvb_avl_checkiftagexist((unsigned char *)TAG_AppPreferName) == 0)
		{
			if((tempAppAppData+tempselectappno)->PreferNameLen)  
		    {
		    	dllemvb_avl_createsettagvalue((unsigned char *)TAG_AppPreferName,(tempAppAppData+tempselectappno)->PreferName,(tempAppAppData+tempselectappno)->PreferNameLen);
		    }
		}

		if(dllemvb_avl_checkiftagexist((unsigned char *)TAG_LangPrefer) == 0)
		{
			if((tempAppAppData+tempselectappno)->LangPreferLen)  
		    {
		    	dllemvb_avl_createsettagvalue((unsigned char *)TAG_LangPrefer,(tempAppAppData+tempselectappno)->LangPrefer,(tempAppAppData+tempselectappno)->LangPreferLen);
		    }
		}
        
        if((tempAppAppData+tempselectappno)->ICTILen)
        {
        	dllemvb_avl_set((unsigned char *)TAG_ICTI,(tempAppAppData+tempselectappno)->ICTI);
        }
		else
		{
			dllemvb_avl_delete((unsigned char *)TAG_ICTI);
		}
        
		
	}
    return retCode;
    
	
}


/*******************************************************************
��    ��:
��������: unsigned char Emv_FinalSelectedApp(AppUnionStruct *App_UnionStruct)
��������: Ӧ������ѡ��
��ڲ���: ��
�� �� ֵ: ��
��ص���:
��    ע:
�޸���Ϣ:         20130731
********************************************************************/
unsigned char Emvb_FinalSelectedApp(EMVBAppUnionStruct *App_UnionStruct)
{
	unsigned char retCode;
	
	
	retCode = Emvb_FinalSelect(App_UnionStruct);      //ѡ��Ӧ��
	if(retCode==EMV_OK || retCode==ERR_APP_TIMEOUT) return retCode;
	else if(retCode == qPBOC_READAIDPARAMETERS)       //sxl add 20100930
	{
	    dllemvb_avl_delete((unsigned char *)TAG_PAN);
		return qPBOC_READAIDPARAMETERS;
	}
	
	
	App_UnionStruct->EMVTradeParam->bretforminit = 1;//added on August 18,2005 according to case V2CL0010101.
	return EMV_APPSELECTTRYAGAIN;
	
}


//20130731
void Emvb_JudgeEC(EMVBAppUnionStruct *tempApp_UnionStruct)
{
    unsigned char AmtAuthNum[6],VLPTransLimit[6];
    
	if(tempApp_UnionStruct->EMVTradeParam->VLPIndicator)  //sxl
	{
		memset(AmtAuthNum,0,sizeof(AmtAuthNum));
    	memset(VLPTransLimit,0,sizeof(VLPTransLimit));  //sxl20131024 pinpad����ʱ������ VLPTransLimit ��Ҫ���ó�ʼ��ֵ

		dllemvb_avl_gettagvalue_spec((unsigned char *)TAG_AmtAuthNum,AmtAuthNum,0,6);
		dllemvb_avl_gettagvalue_spec((unsigned char *)TAG_VLPTransLimit,VLPTransLimit,0,6);

		if(memcmp(AmtAuthNum,VLPTransLimit,6) < 0)
		{
			dllemvb_avl_set((unsigned char *)TAG_VLPIndicator,0x01);  //sxl20131024 pinpad ����ʱ�������Ƿ�Ҫ����EMVNowtask
		}

		
	}
    
    
	
}



/*******************************************************************
��    ��: sxl
��������: unsigned char Paywave_PDOLProcess(AppUnionStruct *tempApp_UnionStruct,APDU_SEND *apdu_s)
��������: ��֯����GPO����
��ڲ���: ��
�� �� ֵ: ��
��ص���:
��    ע:
�޸���Ϣ:    20130731
********************************************************************/
unsigned char Emvb_PDOLProcess(EMVBAppUnionStruct *tempApp_UnionStruct,APDU_SEND *apdu_s)
{
	
	unsigned char *pdolData;       //[255]
	unsigned short index,indexOut;
	//unsigned char k,m;//,bInTable;  //,buf[255]
	unsigned char len;
	EMVTAGCVLITEM *item;
	unsigned char *PDOL;           //[300]
	unsigned char tag[4],taglen;
	//EMVTAGCVLITEM *pdoldataitem = NULL;
	//unsigned char tempTermTransPredicable;
	unsigned short tempPDOLlen;    //templen,
	unsigned char PDOLbexist = 0;
    unsigned char *pdata;
    
    #ifdef EMVB_DEBUG
	unsigned char i;
	#endif
	
	
	tempApp_UnionStruct->EMVTradeParam->onlinetradestatus = 0;
	//dllemvb_avl_set((unsigned char *)TAG_VLPIndicator,0);
	
    
	item = dllemvb_avl_gettagitempointer((unsigned char *)TAG_PDOL);
	if(item != NULL)
	{	
		if(item->len)
		{
			PDOLbexist = 1;
		}
	}
    
	
	if(PDOLbexist == 0)
	{
		memcpy(apdu_s->Command,"\x80\xA8\x00\x00",4); 
		apdu_s->Lc=2;
		memcpy(apdu_s->DataIn,"\x83\x00",2);
		apdu_s->Le=256;
		apdu_s->EnableCancel = 1;    //����ȡ��
		return EMV_OK;
	}
    

	
	pdata = (unsigned char *)emvblib_malloc(600);
    pdolData = &pdata[0];
    PDOL = &pdata[300];
	
    // ע��ָ��
	//PDOL Ϊ��
	memset(pdolData,0,255);
	
	#ifdef EMVB_DEBUG
    emvb_printf("\r\nPaywaveb_PDOLProcess\r\n");
    for(i = 0;i < item->len;i++)
    {
    	emvb_printf("%02x ",item->data[i]);
    }
	emvb_printf("\r\n");
	#endif

	index=0;
	indexOut=0;
    
    
	memset(PDOL,0,300);
    if(item->len>255)
    {
    	tempPDOLlen = 255;
    }
    else
    {
    	tempPDOLlen = item->len;
    }
    memcpy(PDOL,item->data,tempPDOLlen);
	
	
    
	while(index<tempPDOLlen)//Process PDOL
	{
		if(PDOL[index]==0xFF || PDOL[index]==0x00) {index++; continue;} 
		//bInTable=0;

        taglen = Emvb_GetTag(PDOL,index,tag);
		
		if(!memcmp(tag,"\x9F\x7A",2))
		{
			//Emvb_JudgeEC(tempApp_UnionStruct);
		}
		else if(!memcmp(tag,"\xDF\x69",2))
		{
		    #ifdef EMVB_DEBUG
            emvb_printf("\r\nDF flag1\r\n");
			#endif
			#if 0
		    if(dllemvb_avl_gettagvalue((unsigned char *)TAG_ODAalgrthFlag))   //֧�ֹ����㷨
		    {
		    	
				tempApp_UnionStruct->EMVTradeParam->ODASMstaus= 1;
				#ifdef EMVB_DEBUG
	            emvb_printf("\r\nDF flag2%d\r\n",tempApp_UnionStruct->EMVTradeParam->ODASMstaus);
				#endif
				
		    }
			#endif
		}
		
        
        if(Emvb_DOLDataPack(tag,taglen,&index,PDOL,pdolData,&indexOut) != EMV_OK)
		{
            emvblib_free(pdata);
			return ERR_EMV_IccDataFormat;
		}
		
	}
	// Process PDOL end here
    

	
	dllemvb_avl_createsettagvalue((unsigned char *)TAG_PDOLData,pdolData,indexOut);
	
	//tempterminfo->PDOLDataLen=indexOut;
	//memcpy(tempterminfo->PDOLData,pdolData,indexOut);
    
    
    
	
	memcpy(apdu_s->Command,"\x80\xA8\x00\x00",4);
	apdu_s->Lc=indexOut+2;
	len = 0;
	apdu_s->DataIn[len++]=0x83;

	if((indexOut&0x80)>0)				 //�������ֽ�
	{
		(apdu_s->Lc)++;
		apdu_s->DataIn[len++]=0x81;
		apdu_s->DataIn[len++]=indexOut;   //ֻ��һ���ֽ�
	}
	else
	{
		apdu_s->DataIn[len++]=indexOut;   //ֻ��һ���ֽ�
	}
    
	
	memcpy((unsigned char*)&apdu_s->DataIn[len],pdolData,indexOut);
	apdu_s->Le=256;
	apdu_s->EnableCancel = 1;    //����ȡ��
    
	
	emvblib_free(pdata);
	return EMV_OK;
    
	
}

/*******************************************************************
��    ��:
��������: unsigned char Emv_GPORetData(AppUnionStruct *tempApp_UnionStruct,APDU_RESP *apdu_r)
��������: ����GPO�ص�����
��ڲ���: ��
�� �� ֵ: ��
��ص���:
��    ע:
�޸���Ϣ:         20130731
********************************************************************/
unsigned char Emvb_GPORetData(EMVBAppUnionStruct *tempApp_UnionStruct,APDU_RESP *apdu_r)
{
	unsigned short index,indexTemp,len,lenTemp,cplen,j;
    unsigned char k;  //i,
	unsigned char bInTable;
	//unsigned int unknowlen;
	//unsigned char tag;
	unsigned char ret;
    //EMVTAGCVLITEM *item;
    
	
    
	if(apdu_r->SWA==0x90 && apdu_r->SWB==0x00) //Get Processing Options OK
	{		
		index=0;
		//���ݸ�ʽΪ:��80��+����+AIP(Ӧ�ý�������)+AFL(ÿ4���ֽ���һ���ļ���λ��)
		if(apdu_r->DataOut[index]==0x80)//primitive data
		{	
			if(apdu_r->LenOut<2)
			{
				return ERR_EMV_IccDataFormat;
			}
			index++;
            if(ParseExtLen(apdu_r->DataOut,&index,&len))
            {
            	return ERR_EMV_IccDataFormat;
            }
			
			if(index+len!=apdu_r->LenOut)
				return ERR_EMV_IccDataFormat;

			if(len < 2)
			{
				return ERR_EMV_IccDataFormat;
			}

			if(dllemvb_avl_checkiftagexist((unsigned char *)TAG_AIP))
			{
				return ERR_EMV_IccDataFormat;
			}

			dllemvb_avl_createsettagvalue((unsigned char *)TAG_AIP,apdu_r->DataOut+index,2);
            
			
			index+=2;
			k = (len-2)%4;
			if(k != 0)
			{
				return ERR_EMV_IccDataFormat;
			}
			k=(len-2)/4;//AFL4�ֽڳ���
			cplen = ((unsigned short)k)*4;

            if(cplen)
            {
	            if(dllemvb_avl_checkiftagexist((unsigned char *)TAG_AFL))
				{
					return ERR_EMV_IccDataFormat;
				}
				dllemvb_avl_createsettagvalue((unsigned char *)TAG_AFL,apdu_r->DataOut+index,cplen);
            }
			
		    
			for(j = 0;j<k;j++)
			{
				if(apdu_r->DataOut[index + j*4] == 0)
				{
					return ERR_EMV_IccDataFormat;
				}
			}
			
			index += cplen;

			#ifdef EMVB_DEBUG
            emvb_printf("\r\n Emvb_GPORetData index = %d %d \r\n",index,apdu_r->LenOut);
			#endif
		}
		else if(apdu_r->DataOut[index]==0x77)//TLV coded data
		{
		    //tempApp_UnionStruct->EMVTradeParam->paywavecvntype = 1;
            
			
			index++;
			if(ParseExtLen(apdu_r->DataOut,&index,&lenTemp))
			{
				return ERR_EMV_IccDataFormat;
			}
			
			indexTemp=index;
			while(index<indexTemp+lenTemp)
			{
				if(index>=apdu_r->LenOut) 
				{
					return ERR_EMV_IccDataFormat;
				}
				if(apdu_r->DataOut[index]==0xFF || apdu_r->DataOut[index]==0x00) { index++; continue;}
                ret = Emvb_ParseAndStoreCardResponse(tempApp_UnionStruct,apdu_r->DataOut,&index,&bInTable,2);
				if(ret != EMV_OK)
				{
					return ERR_EMV_IccDataFormat;
				}
                
				
				
			}
			if(index!=indexTemp+lenTemp)
			{
				return ERR_EMV_IccDataFormat;
			}	
		}
		else return ERR_EMV_IccDataFormat;
		
	}
	else if(apdu_r->SWA==0x69 && apdu_r->SWB==0x85)
	{
		return ERR_EMVINITAPP_NOTACCEPED;
	}
	else
	{
		return ERR_EMV_IccReturn;
	}
	
    if(index != apdu_r->LenOut)
    {
    	return ERR_EMV_IccDataFormat;
    }

    #ifdef EMVB_DEBUG
    emvb_printf("\r\nEmvb_GPORetData end \r\n");
	#endif

	if(dllemvb_avl_checkiftagexist((unsigned char *)TAG_AFL)==0 || dllemvb_avl_checkiftagexist((unsigned char *)TAG_AIP)==0)
	{
		return ERR_EMV_IccDataMissing;
	}
	
	
	
	return EMV_OK;
}

/*******************************************************************
��    ��: sxl
��������: unsigned char Paypass_InitialApp(AppUnionStruct *tempApp_UnionStruct)
��������: Ӧ�ó�ʼ��
��ڲ���: ��
�� �� ֵ: ��
��ص���:
��    ע:
�޸���Ϣ:         20130731
********************************************************************/
unsigned char Emvb_InitialApp(EMVBAppUnionStruct *tempApp_UnionStruct)
{
	unsigned char retCode;
    
	
	APDU_SEND apdu_s;
	APDU_RESP apdu_r;
    
    
    tempApp_UnionStruct->EMVTradeParam->ODASMstaus = 0;
	retCode = Emvb_PDOLProcess(tempApp_UnionStruct,&apdu_s);
	if(retCode != EMV_OK)
	{
		return retCode;
	}

    tempApp_UnionStruct->EMVB_qPBOCIccIsoCommand(&apdu_s,&apdu_r);
    if(apdu_r.ReadCardDataOk != EMV_OK)
    {
		return ERR_APP_TIMEOUT;
    }


	retCode = Emvb_GPORetData(tempApp_UnionStruct,&apdu_r);
    
	
    return retCode;
    
	
}





//tempterminfo->AFL[*tempRead_AFL_Num][0]


/*******************************************************************
��    ��: sxl
��������: unsigned char Paywave_ReadAFLRetData(AppUnionStruct *tempApp_UnionStruct,APDU_RESP *apdu_r,unsigned char *tempRead_AFL_Num,unsigned char *tempAFL_RecordNum)
��������: ��AFL���ص����ݽ���
��ڲ���: ��
�� �� ֵ: ��
��ص���:
��    ע:
�޸���Ϣ:      20130731
********************************************************************/
unsigned char Emvb_ReadAFLRetData(EMVBAppUnionStruct *tempApp_UnionStruct,APDU_RESP *apdu_r,unsigned char tempt,unsigned char authdataflag)
{
	unsigned char t;
	unsigned char bInTable;  //i,k,
	unsigned short index,indexAEF,lenAEF;  //len,
	//unsigned char tempreadaflnum;
	//unsigned char tag;
	unsigned char ret;
    
	
	if(!(apdu_r->SWA==0x90 && apdu_r->SWB==0x00)) // ICC parameter Records found fail.
	{
		return ERR_EMV_IccReturn;
	}
	
	index=0;

	t=tempt;
	t>>=3;
	#ifdef EMVB_DEBUG
    emvb_printf("\r\nt = %d\r\n",t);
	#endif
	if((t>=11) && (t<=30))//mofified according to SU Bullitin No.12
	{
		if(authdataflag)
		{
			if(apdu_r->DataOut[index]==0x70) //����SFI��11��30�ļ�¼TAG==70�ͼ�¼���������ѻ���֤
			{	
				if((tempApp_UnionStruct->EMVTradeParam->AuthDataLen+apdu_r->LenOut)>2048)//sxl ��ֹ�ڴ����
				{
					return ERR_EMV_IccDataFormat;
				}
				memcpy((unsigned char*)&tempApp_UnionStruct->EMVTradeParam->AuthData[tempApp_UnionStruct->EMVTradeParam->AuthDataLen],apdu_r->DataOut,apdu_r->LenOut);
				tempApp_UnionStruct->EMVTradeParam->AuthDataLen+=apdu_r->LenOut;
			}
			else//������70����Ϊ�ѻ�������֤�Ѿ�ִ�в�ʧ��
			{
				tempApp_UnionStruct->EMVTradeParam->bErrAuthData=1;
			}
		}
		
		while(apdu_r->DataOut[index]==0xFF || apdu_r->DataOut[index]==0x00)
		{ 
			index++; 
		}

		if(apdu_r->DataOut[index]!=0x70) 
		{				
			//return ERR_EMV_IccDataFormat;
			//indexAEF=index;
			//lenAEF = apdu_r->LenOut;
			return EMV_OK;
		}
		else
		{
			index++;

			if(ParseExtLen(apdu_r->DataOut,&index,&lenAEF))
			{
				return ERR_EMV_IccDataFormat;
			}

			indexAEF=index;
		}

	
		while(index<indexAEF+lenAEF)
		{
			if(index>=apdu_r->LenOut) 
			{					
				return ERR_EMV_IccDataFormat;
			}
			if(apdu_r->DataOut[index]==0xFF || apdu_r->DataOut[index]==0x00) 
			{ 
				index++; 
				continue;
			}

			
			ret = Emvb_ParseAndStoreCardResponse(tempApp_UnionStruct,apdu_r->DataOut,&index,&bInTable,2);
			if(ret != EMV_OK)
			{
				return ERR_EMV_IccDataFormat;
			}

			//if(index < indexAEF+lenAEF)
			//{
				//V2CC 144
				//if(memcmp(tempbuf,&apdu_r->DataOut[index],indexAEF+lenAEF-index)  == 0)
				//{
				//	return ERR_EMV_IccDataFormat;
				//}
				
			//}
			
		}
		if(index!=indexAEF+lenAEF)
		{
			return ERR_EMV_IccDataFormat;
		}

	     //sxl20110325
		if(index<apdu_r->LenOut)
		{
			return ERR_EMV_IccDataFormat;
		}
		
		
		return EMV_OK;
	}
			

	while(apdu_r->DataOut[index]==0xFF || apdu_r->DataOut[index]==0x00)
	{ 
		index++; 
	}

	if(apdu_r->DataOut[index]!=0x70) 
	{				
		return ERR_EMV_IccDataFormat;
	}
	index++;

	if(ParseExtLen(apdu_r->DataOut,&index,&lenAEF))
	{
		return ERR_EMV_IccDataFormat;
	}
	
	if(authdataflag) //add record to authentication data string if it is required.
	{
	    if((tempApp_UnionStruct->EMVTradeParam->AuthDataLen+lenAEF)>2048)//sxl ��ֹ�ڴ����
		{
			return ERR_EMV_IccDataFormat;
		}
		memcpy((unsigned char*)&tempApp_UnionStruct->EMVTradeParam->AuthData[tempApp_UnionStruct->EMVTradeParam->AuthDataLen],(unsigned char*)&apdu_r->DataOut[index],lenAEF);
		tempApp_UnionStruct->EMVTradeParam->AuthDataLen+=lenAEF;
	}

	indexAEF=index;

	
	while(index<indexAEF+lenAEF)
	{
		if(index>=apdu_r->LenOut) 
		{					
			return ERR_EMV_IccDataFormat;
		}
		if(apdu_r->DataOut[index]==0xFF || apdu_r->DataOut[index]==0x00) 
		{ 
			index++; 
			continue;
		}

		
		ret = Emvb_ParseAndStoreCardResponse(tempApp_UnionStruct,apdu_r->DataOut,&index,&bInTable,2);
		if(ret != EMV_OK)
		{
			return ERR_EMV_IccDataFormat;
		}
	}
	if(index!=indexAEF+lenAEF)
	{
		return ERR_EMV_IccDataFormat;
	}

     //sxl20110325
	if(index<apdu_r->LenOut)
	{
		return ERR_EMV_IccDataFormat;
	}
	

	
	return EMV_OK;
}



static const EMVTAG EmvbmandatoryTag[] = 
{
	{TAG_AppExpireDate},
	{TAG_AFL},
	{TAG_PAN},
	{TAG_CDOL1},
	{TAG_CDOL2},
	
	{"\x00\x00\x00\x00"}
};

/*******************************************************************
��    ��:
��������: unsigned char EMVStrPos(unsigned char *Src,unsigned char chr )
��������: ����chr���ַ���Src���±�
��ڲ���: 1.Դ�ַ���; 2.�����ַ�
�� �� ֵ: �ַ��±�
��ص���:
��    ע: �ַ������Ȳ���>0xFE.
�޸���Ϣ:
********************************************************************/
unsigned char EMVStrPos(unsigned char *Src,unsigned char chr )
{
	unsigned char Len;
	unsigned char i;
	Len = strlen((char *)Src);
	for(i=0; i < Len; i++)
	{
		if(Src[i] == chr)
			return i;
	}
	return 0xFF;
}

/*******************************************************************
��    ��: sxl
��������: unsigned char Paywave_DealAFLData(AppUnionStruct *tempApp_UnionStruct,APDU_SEND *apdu_s,unsigned char *tempRead_AFL_Num,unsigned char *tempAFL_RecordNum)
��������: ��AFL
��ڲ���: ��
�� �� ֵ: ��
��ص���:
��    ע:
�޸���Ϣ:   20130731
********************************************************************/
unsigned char Emvb_DealAFLData(EMVBAppUnionStruct *tempApp_UnionStruct)
{
	unsigned char i,j,temp[38],temp2[38];
    EMVTAGCVLITEM *item,*item1;
    
	//unsigned char AIPbExist = 0;
	//unsigned char Track2EquivalentbExist,IssuAppDatabExist,AppCryptbExist,ATCbExist,AFLbExist;
    //unsigned char CryptInfobExist;
	//unsigned char *CryptInfo,tempCryptInfo;
	//unsigned char TransTypeValue;
    //unsigned char TermTransPredicable1;
    
	
	
    i = 0;
	while(1)
	{
		if(memcmp(EmvbmandatoryTag[i].Tag,"\x00\x00\x00\x00",4) == 0)
		{
			break;
		}
        
		if(dllemvb_avl_checkiftagexist((unsigned char *)EmvbmandatoryTag[i].Tag) == 0)
		{
			return ERR_EMV_IccDataFormat;
		}
		i++;
	}
	
	
    #ifdef EMVB_DEBUG
    emvb_printf("\r\nPaywave_DealAFLData1111\r\n");
	#endif
    //tempApp_UnionStruct->EMVTradeParam->PaywaveDRRI = 0;
	
	
	item = dllemvb_avl_gettagitempointer((unsigned char *)TAG_Track2Equ);
	item1 = dllemvb_avl_gettagitempointer((unsigned char *)TAG_PAN);
	if(item != NULL&&item1 != NULL)
	{
	    if(item->len&&item1->len)
	    {
			i = 0;
			memset(temp,0,sizeof(temp));
			EMVBcdToAsc(temp,item->data,item->len);
			i = EMVStrPos(temp,'D');
					    		
			for(j=item1->len-1;j>1;j--)
			{
				if(item1->data[j]!=0xff) break;
			}
			j = j+1;		    		
					    		
			if((item1->data[j-1]&0x0f) == 0x0f)
			{	
				j = j*2 -1;
			}
			else j = j*2;
			EMVBcdToAsc(temp2,item1->data,10);

		
			/*  //SXL �����ã�Ҫ��ԭ
			if( (memcmp(temp,temp2,j)!=0) || (i!=j) )
			{
				#ifdef EMVB_DEBUG
				emvb_printf("tempiccdatatable err1 \r\n");
				#endif
				return ERR_EMV_IccDataFormat;
			}
			*/
	    }
		
	}

	#ifdef EMVB_DEBUG
    emvb_printf("\r\nPaywave_DealAFLData1112\r\n");
	#endif
	
	return Emvb_AFLCheckSDAandCVM(tempApp_UnionStruct);
	
}


/*******************************************************************
��    ��: sxl
��������: unsigned char Paywave_ReadAppData(AppUnionStruct *tempApp_UnionStruct)
��������: ��Ӧ������
��ڲ���: ��
�� �� ֵ: ��
��ص���:
��    ע:
�޸���Ϣ:        20130731
********************************************************************/
unsigned char Emvb_ReadAppData(EMVBAppUnionStruct *tempApp_UnionStruct,unsigned char cardtype)
{
	unsigned char retCode;
    EMVTAGCVLITEM *item;
    unsigned char aflexist = 0;
	unsigned char Read_AFL_Num = 0;
    unsigned char AFL_RecordNum = 0;
	unsigned char AFL_Num;
	APDU_SEND apdu_s;
	APDU_RESP apdu_r;
	unsigned char authdataflag;
	
    tempApp_UnionStruct->EMVTradeParam->AuthDataLen = 0;
    tempApp_UnionStruct->EMVTradeParam->bErrAuthData = 0;
	tempApp_UnionStruct->EMVTradeParam->bErrSDATL = 0;
	
	item = dllemvb_avl_gettagitempointer((unsigned char *)TAG_AFL);
    if(item != NULL)
    {
    	if(item->len>>2)
    	{
    		aflexist = 1;
    	}
        
		if((item->len%4) != 0)
		{
			aflexist = 0;
		}
    }
    
	
	if(aflexist == 0)
	{
		return ERR_EMV_IccDataMissing;
	}


	retCode = EMVB_CheckReadAFL(item);
	if(retCode != EMV_OK)
	{
	    #ifdef EMVB_DEBUG
        emvb_printf("\r\nEMVB_CheckReadAFL err\r\n");
		#endif
		return retCode;
	}


	AFL_Num = item->len>>2;
    tempApp_UnionStruct->EMVTradeParam->AuthDataLen = 0;
	tempApp_UnionStruct->EMVTradeParam->bErrAuthData = 0;

	for(Read_AFL_Num = 0;Read_AFL_Num < AFL_Num;Read_AFL_Num++)
	{
		AFL_RecordNum = item->data[(Read_AFL_Num<<2) + 1];
        
		while(AFL_RecordNum <= item->data[(Read_AFL_Num<<2) + 2])
		{
			Emvb_FormReadAflData(&apdu_s,AFL_RecordNum,item->data[(Read_AFL_Num<<2) + 0]);
            
			
			tempApp_UnionStruct->EMVB_qPBOCIccIsoCommand(&apdu_s,&apdu_r);
		    if(apdu_r.ReadCardDataOk != EMV_OK)
		    {
		        if(cardtype == CARD_QPBOC)
		        {
			        if(Read_AFL_Num == AFL_Num-1 && AFL_RecordNum == item->data[(Read_AFL_Num<<2) + 2])
			        {
			        	return ERR_LASTRECORD;  
			        }
		        }
		    	return ERR_APP_TIMEOUT;
		    }
            
			
			if(AFL_RecordNum<item->data[(Read_AFL_Num<<2) + 1]+item->data[(Read_AFL_Num<<2) + 3])
			{
				authdataflag = 1;
			}
            else
            {
            	authdataflag = 0;
            }
            
			
			//sxl20131024 BOOK3- B1�Ĳ����ظ������������ظ�?
			#ifdef EMVB_DEBUG
            emvb_printf("\r\nitem->data[(Read_AFL_Num<<2) + 0] = %02x\r\n",item->data[(Read_AFL_Num<<2) + 0]);
			#endif

        	retCode = Emvb_ReadAFLRetData(tempApp_UnionStruct,&apdu_r,item->data[(Read_AFL_Num<<2) + 0],authdataflag);
			
			if(retCode != EMV_OK)
			{
				return retCode;
			}
			
			
			if(cardtype == CARD_QPBOC) //��鿨��Ч��
			{
				retCode = qPBOCb_CheckExpDate(tempApp_UnionStruct);
				if(retCode != EMV_OK)
				{
					return retCode;
				}
			}
			
			
			AFL_RecordNum++;
			
		}
		
	}
    
    if(cardtype == CARD_QPBOC)
    {
    	retCode = qPBOCb_DealAFLData(tempApp_UnionStruct);
    }
	else
	{
		retCode = Emvb_DealAFLData(tempApp_UnionStruct);

		if(retCode == EMV_OK)
		{
		    if(dllemvb_avl_gettagvalue((unsigned char *)TAG_VLPIndicator))
		    {
		    	if(dllemvb_avl_checkiftagexist((unsigned char *)TAG_VLPIssuAuthorCode))
				{
					retCode = Emvb_ReadEcData(tempApp_UnionStruct);
					if(retCode == EMV_OK)
					{
						retCode = Emvb_ReadEcResetThreshold(tempApp_UnionStruct);
					}
				}
				else
				{
					dllemvb_avl_set((unsigned char *)TAG_VLPIndicator,0);
				}
		    }
		}
		
		
		
	}
	return retCode;
    
}









//20130731
unsigned char Emvb_ReadEcResetThresholdCmd(APDU_SEND *apdu_s)
{
	memcpy(apdu_s->Command,"\x80\xCA\x9F\x6D",4);
	apdu_s->Lc=0;
	apdu_s->Le=256;
	apdu_s->EnableCancel = 1;
	
	return EMV_OK;
}

//20130731
unsigned char Emvb_ReadEcResetThreshold(EMVBAppUnionStruct *tempApp_UnionStruct)
{
	APDU_SEND apdu_s;
	APDU_RESP apdu_r;
	
    Emvb_ReadEcResetThresholdCmd(&apdu_s);
    
    
	tempApp_UnionStruct->EMVB_qPBOCIccIsoCommand(&apdu_s,&apdu_r);
    if(apdu_r.ReadCardDataOk != EMV_OK)
    {
    	return ERR_APP_TIMEOUT;
    }
    
	
    if(apdu_r.SWA==0x90 && apdu_r.SWB==0x00) 
	{
		if(!memcmp(apdu_r.DataOut,"\x9F\x6D",2))
		{
		    if(apdu_r.DataOut[2] != 6)
		    {
		    	return ERR_EMV_IccCommand;
		    }
			dllemvb_avl_createsettagvalue((unsigned char *)TAG_ECResetThreshold,&apdu_r.DataOut[3],6);
		}
	}
    return EMV_OK;
    
}


#endif


